在 64 位代码中从 [esp] 加载时出现段错误

Segfault when loading from [esp] in 64-bit code

我对 x86 汇编很陌生,我正在尝试构建一个 hello world 程序。我正在尝试制作一个子例程,将单个字节写入标准输出,但我遇到了问题。

mov ebx, [esp+1](加载传递的字节,当我调用子程序时)导致段错误。

我试过对 ebx 寄存器本身进行异或运算,以确保它是空的,以确保它不会与系统调用混淆

_start:
    push 32h
    call _writeByte

    ; This just jumps to an exit routine
    jmp  _exit

_writeByte:
    ; This line causes the problem. If I remove it the program works fine
    mov  ebx, [esp+1]
    xor  ebx, ebx

    mov  eax, 1
    mov  edi, 1
    mov  esi, tmp
    mov  edx, 1
    syscall

    ret

为什么程序会出现段错误?

我在 x64 模式下,就像一群人在评论中建议使用 mov ebx, [rsp+8] 一样有效,因为 esp 只是寄存器的 4 个低字节。堆栈位于虚拟地址 space 的低 4 GiB 之外,因此 ESP != RSP 和 [esp] 将是未映射的页面。

请注意,x86-64 调用约定在寄存器中传递前几个参数,而不是在堆栈中传递,因此您通常根本不想这样做(除非您的函数有很多参数)。