对 64 位寄存器感到困惑 - ASM
Confused about 64-bit registers - ASM
我目前正在学习汇编,我在 64 位 ubuntu 上使用 Intel 语法,使用 nasm。
所以我找到了两个引用系统调用编号的网站:
这个用于 32 位寄存器(eax、ebx、...):https://syscalls.kernelgrok.com
这个用于 64 位寄存器(rax、rbx、...):https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64
问题是当我使用 64 位系统调用编号时我的代码不起作用,但是当我用 'r' 替换 32 位寄存器中的 'e' 时它起作用,所以例如在 sys_write 中,我使用 rbx 而不是 rdi 来存储 fd,并且它有效。
我现在很迷茫。此代码无效:
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
运行 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
ABI。
呼叫号码 和 呼叫约定都不同。
int 0x80
系统调用只查看寄存器的低 32 位,这就是为什么你不应该在 64 位代码中使用它们。
您在 mov rcx, message
评论中发布的代码可以与 mov ecx, message
一起正常工作,依此类推, 如果 它与 mov rcx, message
一起工作.参见 。
请注意,写入 32 位寄存器零扩展到完整的 64 位寄存器,因此您应该始终使用 mov edi, 1
而不是 mov rdi, 1
。 (尽管 NASM 会为您进行此优化以节省代码大小;它们非常等价,以至于某些汇编器会默默地为您进行优化。)
我目前正在学习汇编,我在 64 位 ubuntu 上使用 Intel 语法,使用 nasm。
所以我找到了两个引用系统调用编号的网站:
这个用于 32 位寄存器(eax、ebx、...):https://syscalls.kernelgrok.com
这个用于 64 位寄存器(rax、rbx、...):https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64
问题是当我使用 64 位系统调用编号时我的代码不起作用,但是当我用 'r' 替换 32 位寄存器中的 'e' 时它起作用,所以例如在 sys_write 中,我使用 rbx 而不是 rdi 来存储 fd,并且它有效。
我现在很迷茫。此代码无效:
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
运行 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
ABI。
呼叫号码 和 呼叫约定都不同。
int 0x80
系统调用只查看寄存器的低 32 位,这就是为什么你不应该在 64 位代码中使用它们。
您在 mov rcx, message
评论中发布的代码可以与 mov ecx, message
一起正常工作,依此类推, 如果 它与 mov rcx, message
一起工作.参见
请注意,写入 32 位寄存器零扩展到完整的 64 位寄存器,因此您应该始终使用 mov edi, 1
而不是 mov rdi, 1
。 (尽管 NASM 会为您进行此优化以节省代码大小;它们非常等价,以至于某些汇编器会默默地为您进行优化。)