1

我想交换两个 int 指针。

我可以像这样在C中做到这一点

void swap(int* a, int* b)
    int temp = *a;
    *a = *b;
    *b=temp;

现在我正在尝试在组装中进行,但是请耐心等待,我不明白为什么这不起作用

push %ebp
mov %esp,%ebp   

mov 8(%ebp), %ecx       #a 
mov 12(%ebp), %ebx      #b

mov (%ecx), %eax        #move o a para temp
mov (%ebx), %ecx        #move o b para o a
mov (%eax), %ebx        #move o temp para o b

mov %ebp, %esp
pop %ebp
ret

有人可以解释我做错了什么吗?

4

2 回答 2

2

您的C代码试图交换指针指向的值,但您的汇编代码似乎将值视为指向segmentation faults. 处理这个问题的一种方法是使用额外的寄存器来保存指针和它们指向的值。

32 位CDECL允许我们使用EAX ECXEDX不用担心保存它们的值。我们需要第四个寄存器,我们必须自己保存它。

我还将假设您希望存在帧指针(可以在没有它的情况下编写例程):

push   %ebp
mov    %esp,%ebp
push   %ebx              # Preserve non-volatile EBX register
mov    8(%ebp),%eax      # EAX = Pointer to a (arg1)
mov    12(%ebp),%edx     # EDX = Pointer to b (arg2)
mov    (%eax),%ecx       # Temporarily save value at memory address a (*a) to ECX
mov    (%edx),%ebx       # Temporarily save value at memory address b (*b) to EBX
mov    %ebx,(%eax)       # Move value of b (EBX) to memory address of a (*a)
mov    %ecx,(%edx)       # Move value of a (ECX) to memory address of b (*b)
pop    %ebx              # Restore non-volatile EBX register
pop    %ebp
ret

从理论上讲,您可以完全删除堆栈帧(可能会使调试器中的堆栈跟踪更难跟踪)。该代码可以使用ESP而不是EBP来访问参数:

push   %ebx              # Preserve non-volatile EBX register
mov    8(%esp),%eax      # EAX = Pointer to a
mov    12(%esp),%edx     # EDX = Pointer to b
mov    (%eax),%ecx       # Temporarily save value at memory address a (*a) to ECX
mov    (%edx),%ebx       # Temporarily save value at memory address b (*b) to EBX
mov    %ebx,(%eax)       # Move value of b (EBX) to memory address of a (*a)
mov    %ecx,(%edx)       # Move value of a (ECX) to memory address of b (*b)
pop    %ebx              # Restore non-volatile EBX register
ret

注意:未能保留(每个 32 位CDECL调用约定)非易失性寄存器,如EBXEBPESIEDI是一个错误。在简单的测试代码中它可能看起来可以工作,但在更复杂的代码中,如果没有严格遵守调用约定,则可能会遇到未定义的行为。

于 2017-04-22T19:00:39.857 回答
1

正如 Weather Vane 所说,您显示的 C 代码没有交换两个 int 指针。它正在交换由两个 int 指针指向的两个 int。

但是在您的程序集中,您似乎试图交换由两个 int 指针指向的两个 int,因此您的代码并不是完全失败的原因。

研究这个以了解它的作用,然后试一试:

mov (%ecx), %eax
mov (%ebx), %edx
mov %edx, (%ecx)
mov %eax, (%ebx)
于 2017-04-22T18:41:29.487 回答