我正在尝试编写以下形式的函数:
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;
我使用以下命令在 Linux 上编译它:
nasm -f elf64 swap.asm
它编译没有任何错误。主文件如下:
#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;
}
主文件也会编译。但是,当我运行该程序时出现段错误。有什么我犯错的想法吗?
最佳答案
简短回答:您期待错误的调用约定。您还使用了 32 位指针而不是 64 位指针。
Linux x86-64 应用程序使用 System V AMD64 ABI,它在寄存器 RDI
、RSI
、RDX 中传递前 6 个“常规”参数
、RCX
、R8
、R9
。输入时,a
在 RDI
中,b
在 RSI
中。
对于您的swap
,这简化了您的代码,因为您不需要从堆栈指针的偏移量加载。
swap:
mov eax, [rdi] ; *a to EAX
xchg eax, [rsi] ; Exchange *a with *b
mov [rdi], eax ; EAX to *a
ret
请注意,这不一定是最有效的低级别交换方法。尽管它的指令更少,但这不一定更好,而且在性能方面更差。 GCC 10 for x86-64生成负载到寄存器,然后将两者翻转存储。
关于assembly - x86-64 汇编中的交换函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63583809/