在程序集x86中交换两个int指针

时间:2017-04-22 18:24:30

标签: assembly x86 gas att cdecl

我想交换两个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

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

2 个答案:

答案 0 :(得分:2)

您的 C 代码正在尝试交换指针指向的值,但您的汇编代码似乎将值视为指向segmentation faults的指针。处理此问题的一种方法是使用额外的寄存器来保存指针及其指向的值。

32-bit CDECL允许我们使用 EAX ECX EDX ,而无需担心保存其值。我们需要第四个注册,我们必须自己保留它。

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

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 调用约定)非易失性寄存器,如 EBX EBP < / em>, ESI EDI 是一个错误。在简单的测试代码中,它似乎可以工作,但在更复杂的代码中,如果不严格遵守调用约定,那么对您进行优化可能会遇到未定义的行为。

答案 1 :(得分:1)

正如Weather Vane所说,你所展示的C代码并没有交换两个int指针。它正在交换由两个int指针指向的两个整数。

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

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

mov (%ecx), %eax
mov (%ebx), %edx
mov %edx, (%ecx)
mov %eax, (%ebx)