我正在阅读CS:APP第3版(第3章。图3.7 GAS汇编代码)
long exchange(long* xp, long y)
{
long x = *xp;
*xp = y;
return x;
}
exchange:
movq (%rdi), %rax
movq %rsi, (%rdi)
ret
我想知道为什么下面的汇编代码(1.asm:转换为nasm)不起作用?
我使用c2nasm将工作c函数反汇编为nasm汇编源代码。它与原装配完全不同。
main.cpp:
int main()
{
long a = 4;
// long b = exchange(&a, 3);
long b = exchange2(&a, 3);
printf("[a: %ld] [b: %ld]\n", a, b);
return 0;
}
第1步:
BITS 64
; default rel
default abs
global exchange2
section .text
exchange2:
;;; this code does not works
;;; program output -> [a: 4] [b: 0]
mov rax, [rdi]
mov [rdi], rsi
ret
;;; this code works, generated by c2nasm.
;;; program output -> [a: 3] [b: 4]
; push rbp
; mov rbp, rsp
; sub rsp, 16
; mov qword [rbp+10H], rcx
; mov dword [rbp+18H], edx
; mov rax, qword [rbp+10H]
; mov eax, dword [rax]
; mov dword [rbp-4H], eax
; mov rax, qword [rbp+10H]
; mov edx, dword [rbp+18H]
; mov dword [rax], edx
; mov eax, dword [rbp-4H]
; leave
; ret
编辑:谢谢!
Windows x64 long long exchange(long long*, long long)
的工作版本:
BITS 64
default rel
global _exchange2 ; Windows name-mangling prepends _ to C names
section .text
_exchange2:
mov rax, [rcx]
mov [rcx], rdx
ret
您的示例适用于x86-64 System V ABI,用于Linux,OS X和其他非Windows平台(64位long
,RDI,RSI中的args,...)
您为Windows x64编译,它使用不同的调用约定(RCX,RDX中的args),而long
是32位类型。
你也编译了禁用优化,因此asm充满了存储/重载噪声。通过优化,它基本上是相同的,但具有不同的寄存器。
顺便说一下,你可以使用gcc -O3 -masm=intel
来获得更接近NASM语法的英特尔语法汇编。 (虽然它不是NASM语法;它与寻址模式类似MASM,但仍然使用GAS指令。)