mk1*_*k12 8 64-bit assembly x86-64 nasm cpu-registers
我理解在x86_64汇编中有例如(64位)rax寄存器,但它也可以作为32位寄存器,eax,16位,ax和8位来访问.在什么情况下我不会只使用完整的64位,以及为什么会有什么优势?
举个例子,通过这个简单的hello world程序:
section .data
msg: db "Hello World!", 0x0a, 0x00
len: equ $-msg
section .text
global start
start:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, msg ; The address of hello_world string
mov rdx, len ; The size to write
syscall ; Invoke the kernel
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall ; Invoke the kernel
Run Code Online (Sandbox Code Playgroud)
rdi和rdx,至少只需要8位而不是64位,对吧?但是,如果我将它们分别更改为dil和dl(它们的低8位当量),程序会组装并链接但不输出任何内容.
但是,如果我使用eax,edi和edx,它仍然有效,那么我应该使用那些而不是完整的64位吗?为什么或者为什么不?
你在这里问几个问题.
如果只加载寄存器的低8位,寄存器的其余部分将保持其先前的值.这可以解释为什么你的系统调用得到了错误的参数.
当你需要的时候使用32位的一个原因是许多使用EAX或EBX的指令比使用RAX或RBX的指令短一个字节.它也可能意味着加载到寄存器中的常量更短.
指令集已经发展了很长时间,并且有很多怪癖!
首先也是最重要的是将较小的(例如 8 位)值从内存(读取字符、处理数据结构、反序列化网络数据包等)加载到寄存器中。
MOV AL, [0x1234]
Run Code Online (Sandbox Code Playgroud)
相对
MOV RAX, [0x1234]
SHR RAX, 56
# assuming there are actually 8 accessible bytes at 0x1234,
# and they're the right endianness; otherwise you'd need
# AND RAX, 0xFF or similar...
Run Code Online (Sandbox Code Playgroud)
或者,当然,将所述值写回到内存中。
(编辑,就像 6 年后):
由于这种情况不断出现:
MOV AL, [0x1234]
Run Code Online (Sandbox Code Playgroud)
相比之下:
MOV RAX, [0x1234]
Run Code Online (Sandbox Code Playgroud)
SHR
多年前的指令)还需要注意的是:
MOV EAX, [0x1234]
Run Code Online (Sandbox Code Playgroud)
然后,正如评论中提到的,有:
MOVZX EAX, byte [0x1234]
Run Code Online (Sandbox Code Playgroud)
在所有这些情况下,如果您想从“A”寄存器写入内存,您必须选择宽度:
MOV [0x1234], AL ; write a byte (8 bits)
MOV [0x1234], AX ; write a word (16 bits)
MOV [0x1234], EAX ; write a dword (32 bits)
MOV [0x1234], RAX ; write a qword (64 bits)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4135 次 |
最近记录: |