【问题标题】:Shellsort: Write NASM code from CShellsort:从 C 编写 NASM 代码
【发布时间】:2015-03-10 04:54:07
【问题描述】:

我正在尝试将 C 函数转换为 32 位的 NASM。

这里是 C 函数

void shellsort (int *A, int n)
{
    int gap, i, j, temp;
    for (gap = n/2; gap > 0; gap /=2)
    {
        for (i= gap; i<n; i++)
        {
            for  (j=i-gap; j>=0 && A[j] > A[j+gap]; j-=gap)
            {
                temp = A[j];
                A[j] = A[j+gap]
                A[j+gap] = temp;
            }
        }
    }
}

这是我到目前为止所做的事情

%include "asm_io.inc"

SECTION .data

SECTION .bss

SECTION .text

extern printf

global sort

sort:

    push ebp                            ;set up stack frame
    mov ebp, esp

    sub esp, 0x10                       ;assign 16byte space for local variables

firstloop:

    mov eax, [ebp+8]                    ;moves value of n into eax
    mov edx, 0                          ;prepares for division, remainder init
    mov ecx, 2                          ;divisor

    div ecx                             ;division, store gap in eax

    cmp eax, 0                          ;compare if gap with zero
    jle firstloopDone                   ;firstloopDone

firstloopDone:

    div ecx
    jmp done

secondloop:

    mov ecx, eax                        ;copy value of gap into ecx, i=gap
    cmp ecx, [ebp+8]                    ;compare i with 1st parameter n

    jge secondloopDone                  ;jump to secondloop if greater-equal
    inc ecx                             ;increment i
    jmp thirdloop                       ;jump to thirdloop

secondloopDone:

    inc ecx                             ;increment i
    jmp firstloop                       ;jump to firstloop

thirdloop:

    mov edx, ecx                        ;save i value
    sub ecx, eax                        ;subtract gap from i and store in ecx

    cmp ecx, 0                          ;compare j with zero
    jl thirdloopDone                    ;if not j>=0, then skip to end of loop

    cmp [ebp+12+ecx], [ebp+12+ecx+eax]  ;compare A[j] and A[j+gap]
    jle thirdloopDone
    sub ecx, eax                        ;subtract gap from j and store in ecx
    jmp swap

thirdloopDone:

    sub ecx, eax                        ;j-gap
    jmp secondloop                      ;jump to second loop

swap:

    mov edx, [ebp+12+ecx]               ;copy A[j] to temp
    mov [ebp+12+ecx], [ebp+12+ecx+eax]  ;A[j]=A[j+gap]
    mov [edp+12+ecx+eax], edx           ;A[j+gap]= temp
    jmp thirdloop

done:

    leave                               ;destroy stack frame
    ret

不用说,它不起作用。 错误消息说:

“错误:beroset-p-603-无效的有效地址”

在第 58 行(第三次循环)

cmp [ebp+12+ecx], [ebp+12+ecx+eax]

在第 71 行(交换)

mov edx, [ebp+12+ecx]

我知道这可能是错误的方法。但是从 C 代码中的嵌套循环来看,我有太多的变量要保留,所以我无法节省任何寄存器。

另外,我怀疑我可能没有正确理解堆栈帧,这可能会显示在我的代码中。

任何帮助或错误发现,将不胜感激。谢谢。

【问题讨论】:

  • “我有太多变量要保留,所以我无法节省任何寄存器”。在堆栈上临时保存一个或多个寄存器,或使用内存变量。
  • 另外,除以 2 相当于在 base-2 中右移 1。这应该会稍微简化您的除法程序。
  • Michael,我尝试使用堆栈,但由于循环,我无法跟踪所有推送和弹出。我只使用寄存器。丹尼尔,谢谢你的提示!这真的很有帮助!

标签: c sorting assembly nasm shellsort


【解决方案1】:

你说你没有足够的寄存器来玩,但你甚至没有使用 EBX、ESI 或 EDI。您为局部变量做出了规定,但您没有使用任何变量。

firstloop:
 mov eax, [ebp+8]                    ;moves value of n into eax
 mov edx, 0                          ;prepares for division, remainder init
 mov ecx, 2                          ;divisor
 div ecx                             ;division, store gap in eax

前面的代码不需要除法。使用移位操作简化它。 shr eax,1

下一个代码总是会终止。使用jle done

 cmp eax, 0                          ;compare if gap with zero
 jle firstloopDone                   ;firstloopDone
firstloopDone:
 div ecx
 jmp done

参数不是从右向左推送的吗?

 mov ebx, [ebp+8]   ;pointer to array A
firstloop:
 mov eax, [ebp+12]  ;number of elemnets n

您通常需要编写代码

swap:
 mov  edx, [ebx+ecx*4]  ;TEMP=A[j]
 add  ecx,eax
 xchg edx, [ebx+ecx*4]  ;Swap A[j+gap] with TEMP
 sub  ecx, eax
 mov  [ebx+ecx*4], edx  ;A[j]=TEMP
 jmp  thirdloop

【讨论】:

  • 我重新编写了整个代码,它现在可以工作了。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2013-06-28
  • 2014-01-03
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多