i am reading CS:APP 3rd edition (Ch3. pic 3.7 GAS assembly code)
long exchange(long* xp, long y)
{
long x = *xp;
*xp = y;
return x;
}
exchange:
movq (%rdi), %rax
movq %rsi, (%rdi)
ret
i wonder why below assembly code(1. asm : which is converted to nasm) does not work?
i had diassembled working c function to nasm assembly source code using c2nasm. it is quite different to original assembly.
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.asm :
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
EDIT: thanks!
working version for 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
Your example is for the x86-64 System V ABI, used on Linux, OS X, and other non-Windows platforms (64-bit long
, args in RDI, RSI, ...)
You compiled for Windows x64, which uses a different calling convention (args in RCX, RDX), and long
is a 32-bit type.
Also you compiled with optimization disabled so the asm is full of store/reload noise. With optimization it would be basically the same but with different registers.
BTW, you can use gcc -O3 -masm=intel
to get Intel-syntax assembly which is a lot closer to NASM syntax. (It's not NASM syntax though; it's MASM-like for addressing modes, and still uses GAS directives.)