【问题标题】:Assembler program to swap contents of registers交换寄存器内容的汇编程序
【发布时间】:2021-07-21 03:47:31
【问题描述】:

我正在尝试做一个真正简单的汇编程序来交换寄存器的内容。这是我尝试过的:

movq (%rcx), %rax
movq (%rbx), %rdx
movq %rdx, (%rcx)
movq %rax, (%rbx)
ret

它给了我分段错误。

这是一个 c 中的工作程序示例:

void swap(int64_t *a, int64_t *b) {
    int64_t c = *a;
    *a = *b;
    *b = c;
}

【问题讨论】:

  • 你能解释一下你希望这些指令做什么吗?是哪一个导致了故障?
  • 你是如何编译你的程序集的?请提供一个可重现的最小示例。
  • 欢迎来到 StackOverflow!请使用tour 并阅读“How to Ask”。然后回来edit你的问题,请提供minimal reproducible example
  • 标题说“交换寄存器的内容”,但示例是关于内存位置的。要交换寄存器,您可以使用xchg
  • Godbolt 产生不同的程序集(寄存器使用,-O3 优化):godbolt.org/z/dYYeYYrz1

标签: c assembly segmentation-fault x86-64 calling-convention


【解决方案1】:

见:https://en.wikipedia.org/wiki/X86_calling_conventions

您忽略了您是为 Microsoft/Win x64 还是为 System V AMD64 ABI [或完全为其他东西] 进行编译。

您使用的是 AT&T asm 语法,所以我假设您需要 SysV 调用约定。 (由于 GCC 和 GAS 等工具在 Linux / MacOS 上更常见。但如果您在 Windows 上使用 MinGW w64,那么您将需要 Windows 约定。)


您假设参数位于:%rcx%rbx。这确实符合任何一个约定[尽管它更接近MS ABI]

对于 System V AMD64 ABI(例如 Linux、BSD、MacOS),前两个参数分别在 %rdi%rsi 中传递。而且,not%rdx%rcx(用于第三和第四个参数)。

您始终可以使用 %rax%rdx 作为临时注册,因为 %rax 保存函数返回值,而 %rdx 是一个 arg 注册,因此调用者不会期望它们被保留。

所以,你想要:

# Non-Windows
movq (%rdi),%rax
movq (%rsi),%rdx
movq %rdx,(%rdi)
movq %rax,(%rsi)
ret

对于 MS 64 位,arg 寄存器为:%rcx, %rdx, %r8, %r9

所以,你会想要:

# Windows
movq (%rcx),%rax
movq (%rdx),%r8
movq %r8,(%rcx)
movq %rax,(%rdx)
ret

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-01-02
  • 2019-12-26
  • 1970-01-01
  • 2021-03-25
  • 2013-06-17
  • 2015-11-01
  • 2014-12-15
  • 2016-11-11
相关资源
最近更新 更多