oll*_*lpu 1 x86 assembly x86-64 machine-code addressing-mode
我对x86-64二进制编码很新.我正在尝试修复一些旧的"汇编程序"代码.
无论如何,我正在尝试做这样的事情(英特尔语法):
mov [rbp+rcx], al
Run Code Online (Sandbox Code Playgroud)
汇编程序目前正在生成:
88 04 0D
Run Code Online (Sandbox Code Playgroud)
但这似乎不是一个有效的指示.如果我将SIB字节中的基数更改rbp
为其他寄存器,则可以正常工作.另一种使其工作的方法是添加一个零字节的位移(88 44 0D 00
).这似乎与其他类似的操作码一起发生.
为什么我不能rbp
在那里使用mod=00
?
编码意味着rbp
没有基址寄存器的转义码(只是SIB中的disp32或ModRM中的RIP相对rel32).大多数装配工装[rbp]
配成[rbp + disp8=0]
.
由于您不需要缩放,因此请使用[rcx + rbp]
以避免需要disp8 = 0,因为它rbp
可以是索引.
(SS和DS在长模式下始终是等效的,因此base = RBP意味着SS而base = RCX意味着使用DS段并不重要.)
(从我写的答案为什么rbp和rsp称为通用寄存器?).这个问题看起来像是复制或移植这一部分的理想场所.
rbp
/ r13
不能是没有位移的基址寄存器:该编码代替:(在ModRM中)rel32
(RIP相对),或(在SIB中)disp32
没有基址寄存器.(r13
在ModRM/SIB中使用相同的3位,因此该选择通过不使指令长度解码器查看REX.B位以获得第4个基址寄存器位来简化解码). [r13]
装配到[r13 + disp8=0]
. [r13+rdx]
汇编到[rdx+r13]
(当这是一个选项时,通过交换base/index 来避免问题).
rsp
/ r12
作为基址寄存器总是需要一个SIB字节.(base = RSP的ModR/M编码是用于发信号通知SIB字节的转义码,并且如果r12
处理不同,则更多的解码器将不得不关心REX前缀).
rsp
不能成为索引注册.这使得编码成为可能[rsp]
,这比编码更有用[rsp + rsp]
.(英特尔本可以设计用于32位寻址模式的ModRM/SIB编码(386中的新功能),因此只能使用base = ESP进行SIB-no-index.这样就[eax + esp*4]
可以并且只能排除[esp + esp*1/2/4/8]
.但这没有用,所以他们简化了硬件,使index = ESP成为无索引的代码,无论基数如何.这允许两种冗余方式对任何base或base + disp寻址模式进行编码:有或没有SIB.)
r12
可以是索引寄存器.与其他情况不同,这不会影响指令长度解码.此外,它不能像其他情况一样使用更长的编码.AMD希望AMD64的寄存器设置尽可能正交,因此有必要花一些额外的晶体管来检查REX.X作为索引/无索引解码的一部分.例如,[rsp + r12*4]
要求index = r12,因此r12
没有完全通用的目的会使AMD64成为更糟糕的编译器目标.
0: 41 8b 03 mov eax,DWORD PTR [r11]
3: 41 8b 04 24 mov eax,DWORD PTR [r12] # needs a SIB like RSP
7: 41 8b 45 00 mov eax,DWORD PTR [r13+0x0] # needs a disp8 like RBP
b: 41 8b 06 mov eax,DWORD PTR [r14]
e: 41 8b 07 mov eax,DWORD PTR [r15]
11: 43 8b 04 e3 mov eax,DWORD PTR [r11+r12*8] # *can* be an index
Run Code Online (Sandbox Code Playgroud)
这些都适用于32位寻址模式; 编码是相同的,除了没有EIP相关编码,只有两种冗余方式来编码没有基数的disp32.
有关像英特尔vol.2手册中的表格,请参阅https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2.
这似乎与其他类似的操作码一起发生.
r/m操作数的ModRM编码始终相同.某些操作码需要一个寄存器操作数,有些需要内存,但实际的ModRM +可选SIB +可选位移是固定的,因此无论指令如何,相同的硬件都可以对其进行解码.
有一些罕见的操作码,例如mov al/ax/eax/rax, [qword absolute_address]
根本不使用ModRM编码作为操作数,但任何使用相同格式的操作码.