分享
三行代码  ›  专栏  ›  技术社区  ›  Ajvar

对64位寄存器感到困惑-ASM

  •  0
  • Ajvar  · 技术社区  · 2 天前

    所以我找到了两个引用syscalls号码的网站:

    这个用于32位寄存器(eax,ebx,…): https://syscalls.kernelgrok.com

    https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64

    问题是,当我使用64位系统调用号时,我的代码不起作用,但当我将32位寄存器中的“e”替换为“r”时,它起作用,因此,例如在sys_write中,我使用rbx来存储fd,而不是rdi as,它起作用。

    message db 'Hello, World', 10
    
    section .text
    global _start
    _start: mov rax,4
            mov rdi, 1
            mov rsi, message
            mov rdx, 13
            syscall
            mov rax, 1
            mov rdi, 0
            syscall
    
    1 回复  |  直到 2 天前
        1
  •  2
  •   Peter Cordes    2 天前

    跑步 strace ./my_program -你造假了 stat 系统调用,然后 write

    $ strace ./foo 
    execve("./foo", ["./foo"], 0x7ffe6b91aa00 /* 51 vars */) = 0
    stat(0x1, 0x401000)                     = -1 EFAULT (Bad address)
    write(0, "Hello, World\n", 13Hello, World
    )          = 13
    --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xd} ---
    +++ killed by SIGSEGV (core dumped) +++
    Segmentation fault (core dumped)
    

    你的问题不是登记姓名,而是电话号码。您使用的是32位呼叫号码,但调用的是64位 syscall 阿比。

    电话号码

    int 0x80 系统调用只查看寄存器的低32位,这就是为什么不应该在64位代码中使用它们。

    你在评论中发布的代码 mov rcx, message mov ecx, message 等等, 如果 它与 mov rcx,消息 . 见 What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? .

    请注意,写入32位寄存器0会扩展到完整的64位寄存器,因此您应该始终使用 mov edi, 1 mov rdi, 1 . (尽管NASM会为您执行此优化以节省代码大小;但它们是如此等效,以至于一些汇编程序会默默地为您执行此优化。)