x86-64 汇编中的交换函数

Ara*_*ani 1 assembly x86-64

我正在尝试编写以下形式的函数:

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

在 x86-64 汇编中。

[section .text]
global  swap ;
swap: mov ecx, [esp+8] ; copy parameter a to ecx
mov edx, [esp+16] ; copy parameter b to edx
mov eax, [ecx] ; copy a into eax
xchg eax, [edx] ; exchange eax with b
mov [ecx], eax;
ret;
Run Code Online (Sandbox Code Playgroud)

我使用以下命令在 Linux 上编译它:

nasm -f elf64 swap.asm
Run Code Online (Sandbox Code Playgroud)

它编译没有任何错误。主要文件如下:

 #include <stdio.h>
 extern void swap(int *a,int *b);
 int main(){
          int a = 10, int b = 20;
          swap(&a,&b);
          printf("a = %d b = %d\n",a,b );
          return 0;
 }
Run Code Online (Sandbox Code Playgroud)

主文件也编译。但是,运行此程序时出现分段错误。我犯错的任何想法?

Tho*_*ger 7

简短回答:您期待错误的调用约定。您还使用了 32 位指针而不是 64 位指针。


Linux x86-64 应用程序使用 System V AMD64 ABI,它具有在寄存器RDI, RSI, RDX, RCX, R8, 中传递的前 6 个“常规”参数R9。进入时,aRDI,并且bRSI

对于您的swap,这简化了您的代码,因为您不需要从堆栈指针的偏移量加载。


swap:
    mov eax, [rdi]    ; *a to EAX
    xchg eax, [rsi]   ; Exchange *a with *b
    mov [rdi], eax    ; EAX to *a
    ret
Run Code Online (Sandbox Code Playgroud)

请注意,这不一定是交换的最有效方法,在低级别。尽管指令较少,但这并不一定更好,而且在性能方面更差。适用于 x86-64 的 GCC 10生成加载到寄存器,然后存储两个翻转。

  • 值得指出*为什么*它慢得要命:带有内存的“xchg”有一个隐式的“lock”前缀,所以它是一个带有完整内存屏障的原子交换。 (4认同)