assembly - x86-64 汇编中的交换函数

标签 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;

我使用以下命令在 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,它在寄存器 RDIRSIRDX 中传递前 6 个“常规”参数RCXR8R9。输入时,aRDI 中,bRSI 中。

对于您的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/

相关文章:

assembly - 'callq *(%rax)' 是什么意思?

memory - 低级编程: How to find data in a memory of another running process?

c++ - 编辑 C++/汇编调试器的源代码以包含额外的汇编信息?

assembly - nasm x86_64 中的 strcmp,寄存器

windows - 什么导致页面错误?

AMD64 上的 ruby​​ postgreSQL 适配器

assembly - USB 硬盘模拟导致磁盘读取失败(BIOS int 13)?

assembly - 使用 16 位模式打印字母,无需 BIOS 例程

linux - 如何计算进程中可用的 "Max Contiguous Free Space"?

java - 如何构建 netty-transport-native-epoll-4.0.32.Final-linux-x86_64.jar?