x86-64 汇编中的交换函数
Swap function in x86-64 assembly
我正在尝试编写以下形式的函数:
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
、[=13= 中传递了前 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
请注意,这不一定是最有效的低级别交换方法。尽管它的指令更少,但这不一定更好,而且更糟 performance-wise。 GCC 10 for 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;
我使用以下命令在 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
、[=13= 中传递了前 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
请注意,这不一定是最有效的低级别交换方法。尽管它的指令更少,但这不一定更好,而且更糟 performance-wise。 GCC 10 for x86-64 向寄存器生成负载,然后将两者翻转存储。