如何知道使用哪个整数寄存器
How to know which integer register to use
我正在尝试学习汇编,这在一定程度上是有道理的,但我遇到了问题。我有这个源文件 hello.sfml
:
; nasm -felf64 hello.asml && ld hello.o
global _start
section .text
_start:
; write(1, message, 13)
mov rax, 1 ; syscall 1 is write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 13 ; number of bytes in the string
syscall ; invoke OS to write the string
; exit(0)
mov rax, 60 ; syscall 60 is exit
xor rdi, rdi
syscall ; invoke OS to exit
message:
db "Hello, World", 10 ; the 10 is a newline character at the end
效果很好。我只是不明白为什么需要在不同情况下使用特定的整数寄存器。
因此,例如,通过反复试验,我发现在说出我想要的系统调用时,例如
mov rax, 1
...
syscall
我把值1
放入整数寄存器rax
,但我也可以使用整数寄存器eax
、ax
、al
,或 ah
.
我学习汇编的时间不长,所以这很可能是一个很明显的问题。
如果我的问题不是很明显:我想知道如何决定将值移动到哪个整数寄存器,例如如果有一些通用系统,或者如果每个不同的意图使用不同的整数寄存器。
我在 64 位 Ubuntu 上使用 NASM。
编辑: 我的问题不是 this one, 的重复,因为那个人问的是你会在哪里使用 smaller整数寄存器,我要求一种方法来决定 使用哪个 整数寄存器。
程序集或 x86 机器没有定义您应该使用哪个通用寄存器 (GPR),您可以使用任何可用的 GPR(或提供一个),但是,不同的环境定义了不同的寄存器使用和参数约定通过,当你想使用别人的代码时,你必须遵守这些约定。
具体来说,Linux x86-64 使用以下约定,如 X86 psABI(第 3.2.3 节)所述:
- If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used.
如果是标准的用户级代码,就是上面第一个例子中选择rdi
、rsi
和rdx
的原因,第一个参数是在 rdi
中传递,第二个在 rsi
中传递,第三个在 rdx
中传递。
不过,上面的例子演示了Linux系统调用的内核内部调用约定,它类似于用户级应用程序,但有一些差异(第A.2.1节):
- User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
- A system-call is done via the syscall instruction. The kernel destroys registers %rcx and %r11.
- The number of the syscall has to be passed in register %rax.
正如您在示例中所见,每个系统调用都基于 Linux System Call Table for x86-64(如 zx485 所评论)定义了 rax 值。
请注意,系统调用最多可以有 6 个参数,并且与用户级代码不同,不能使用堆栈来获取额外参数。
Windows、32 位或其他环境有不同的 ABI,但我不会在这里详细说明。
关于您对 al
、ax
和 eax
用法的评论:当使用 x86-64 架构时,要求是在 rax 中指定系统调用的数量,使用任何寄存器的其他部分是基于运气的——如果寄存器其他部分的所有位都是零,那么你可以使用较低的位——但你不应该相信它。
提醒:
rax is the full 64-bit register
eax is the lower 32-bits
ax is the lower 16-bits
al is the lower 8 bits
ah is the value in bits 8 through 15
如您所见,使用 ah
是错误的,可能会调用不同的系统调用!
我正在尝试学习汇编,这在一定程度上是有道理的,但我遇到了问题。我有这个源文件 hello.sfml
:
; nasm -felf64 hello.asml && ld hello.o
global _start
section .text
_start:
; write(1, message, 13)
mov rax, 1 ; syscall 1 is write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 13 ; number of bytes in the string
syscall ; invoke OS to write the string
; exit(0)
mov rax, 60 ; syscall 60 is exit
xor rdi, rdi
syscall ; invoke OS to exit
message:
db "Hello, World", 10 ; the 10 is a newline character at the end
效果很好。我只是不明白为什么需要在不同情况下使用特定的整数寄存器。
因此,例如,通过反复试验,我发现在说出我想要的系统调用时,例如
mov rax, 1
...
syscall
我把值1
放入整数寄存器rax
,但我也可以使用整数寄存器eax
、ax
、al
,或 ah
.
我学习汇编的时间不长,所以这很可能是一个很明显的问题。
如果我的问题不是很明显:我想知道如何决定将值移动到哪个整数寄存器,例如如果有一些通用系统,或者如果每个不同的意图使用不同的整数寄存器。
我在 64 位 Ubuntu 上使用 NASM。
编辑: 我的问题不是 this one, 的重复,因为那个人问的是你会在哪里使用 smaller整数寄存器,我要求一种方法来决定 使用哪个 整数寄存器。
程序集或 x86 机器没有定义您应该使用哪个通用寄存器 (GPR),您可以使用任何可用的 GPR(或提供一个),但是,不同的环境定义了不同的寄存器使用和参数约定通过,当你想使用别人的代码时,你必须遵守这些约定。
具体来说,Linux x86-64 使用以下约定,如 X86 psABI(第 3.2.3 节)所述:
- If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used.
如果是标准的用户级代码,就是上面第一个例子中选择rdi
、rsi
和rdx
的原因,第一个参数是在 rdi
中传递,第二个在 rsi
中传递,第三个在 rdx
中传递。
不过,上面的例子演示了Linux系统调用的内核内部调用约定,它类似于用户级应用程序,但有一些差异(第A.2.1节):
- User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
- A system-call is done via the syscall instruction. The kernel destroys registers %rcx and %r11.
- The number of the syscall has to be passed in register %rax.
正如您在示例中所见,每个系统调用都基于 Linux System Call Table for x86-64(如 zx485 所评论)定义了 rax 值。
请注意,系统调用最多可以有 6 个参数,并且与用户级代码不同,不能使用堆栈来获取额外参数。
Windows、32 位或其他环境有不同的 ABI,但我不会在这里详细说明。
关于您对 al
、ax
和 eax
用法的评论:当使用 x86-64 架构时,要求是在 rax 中指定系统调用的数量,使用任何寄存器的其他部分是基于运气的——如果寄存器其他部分的所有位都是零,那么你可以使用较低的位——但你不应该相信它。
提醒:
rax is the full 64-bit register
eax is the lower 32-bits
ax is the lower 16-bits
al is the lower 8 bits
ah is the value in bits 8 through 15
如您所见,使用 ah
是错误的,可能会调用不同的系统调用!