在我的Ubuntu机器上尝试使用NASM和GCC制作一个非常小的程序时,我发现了一些奇怪的东西。
以下代码在64位NASM和GCC下编译良好:
global main
extern puts
section .text
main:
push rax
mov rdi, message
call puts
jmp exit
exit:
;return stack memory
pop rax
ret
message:
db "Hello from NASM!", 0
但是当尝试在32位NASM和GCC下编译相同的代码(仅更改寄存器)时,它将导致分段错误和/或随机字符。为什么会这样?与i386相比,x64架构在将内存存储到堆栈方面有不同的方式吗?如果是这样,如何防止这种行为?
答案 0 :(得分:3)
在32位模式下,大多数调用约定(cdecl
,stdcall
等...)期望将参数压入堆栈,而不是寄存器,与64位模式不同,您还需要在调用puts
后调整堆栈指针,因此您需要执行以下操作:
lea edx, @message
push edx
call puts
add esp, 4
使程序在32位模式下产生相同的输出。我可能没有正确的NASM语法,因为我通常在MASM和GAS中编写汇编代码。