x86 在执行指令和 reading/writing 数据时如何处理字节寻址与字寻址?
How does x86 handle byte vs word addressing when executing instructions and reading/writing data?
所以我正在学习 x86 的工作原理,并且遇到过有人说它是字节可寻址的,但可以读取字、双字等。
处理器如何决定使用哪种方法以及何时使用?
例如。为了访问下一条指令以及当用户想要 read/write 到内存时,使用哪种寻址模式?
每个内存访问都有一个由机器代码指令指定的操作数大小。(寻址模式不是正确的术语:不同的寻址模式是指定内存的不同方式要访问的内存块的最低地址,如 [rdi]
与 [rdi + rdx*8]
与 [RIP + rel32]
)
编码不同的操作数大小是通过前缀(整数指令的 16 位、32 位和 64 位)或相同助记符(8 位整数)的不同操作码完成的。 或者使用 VEX 或 EVEX 前缀中的位,用于 AVX/AVX512 指令,可以使用 xmm、ymm 或 zmm 寄存器。
解码还取决于当前模式,即默认操作数大小:32 位和 64 位模式为 32,16 位模式为 16。 66
操作数大小前缀表示相反的大小。
在 64 位模式下,REX 前缀中的 .W
(宽度)位将操作数大小设置为 64 位。 (有些指令如 push
/pop
默认为 64 位操作数大小,不需要前缀,但大多数指令如 add
/sub
/mov
仍默认为 32 位)
还有一个 0x67
地址大小前缀,可将寻址模式转换为其他大小。 (16 对 32 或 64 位模式 64 -> 32。)
例如,mov [rdi], eax
是一个双字存储,机器代码编码将通过在 16/32/64 位操作数大小的操作码上不使用特殊前缀来指定。 (有关可用编码,请参阅 https://www.felixcloutier.com/x86/mov。但请注意,英特尔的手册 没有 在每个条目中提及 66
操作数大小前缀:它有 2 个相同的编码不同的尺寸。你必须根据当前模式的默认值知道哪个需要 66
前缀。)
16 位操作数大小如 mov [rdi], ax
将具有与 66
操作数大小前缀相同的机器代码。
8 位操作数大小 (mov [rdi], al
) 有自己的操作码,不需要前缀。
movzx
/ movsx
是有趣的情况:内存访问大小与目标寄存器不同。内存访问大小(字节或字)由操作码指定。操作数大小前缀只影响目标大小。 x86-64 63 /r
movsxd
(双字->qword 符号扩展)除外,其中 66
操作数大小前缀 会 缩小内存访问缩小到 m16
以匹配目的地。
SIMD 指令类似;指令编码唯一地确定内存访问大小,以及读取或写入的寄存器。
所以我正在学习 x86 的工作原理,并且遇到过有人说它是字节可寻址的,但可以读取字、双字等。 处理器如何决定使用哪种方法以及何时使用? 例如。为了访问下一条指令以及当用户想要 read/write 到内存时,使用哪种寻址模式?
每个内存访问都有一个由机器代码指令指定的操作数大小。(寻址模式不是正确的术语:不同的寻址模式是指定内存的不同方式要访问的内存块的最低地址,如 [rdi]
与 [rdi + rdx*8]
与 [RIP + rel32]
)
编码不同的操作数大小是通过前缀(整数指令的 16 位、32 位和 64 位)或相同助记符(8 位整数)的不同操作码完成的。 或者使用 VEX 或 EVEX 前缀中的位,用于 AVX/AVX512 指令,可以使用 xmm、ymm 或 zmm 寄存器。
解码还取决于当前模式,即默认操作数大小:32 位和 64 位模式为 32,16 位模式为 16。 66
操作数大小前缀表示相反的大小。
在 64 位模式下,REX 前缀中的 .W
(宽度)位将操作数大小设置为 64 位。 (有些指令如 push
/pop
默认为 64 位操作数大小,不需要前缀,但大多数指令如 add
/sub
/mov
仍默认为 32 位)
还有一个 0x67
地址大小前缀,可将寻址模式转换为其他大小。 (16 对 32 或 64 位模式 64 -> 32。)
例如,mov [rdi], eax
是一个双字存储,机器代码编码将通过在 16/32/64 位操作数大小的操作码上不使用特殊前缀来指定。 (有关可用编码,请参阅 https://www.felixcloutier.com/x86/mov。但请注意,英特尔的手册 没有 在每个条目中提及 66
操作数大小前缀:它有 2 个相同的编码不同的尺寸。你必须根据当前模式的默认值知道哪个需要 66
前缀。)
16 位操作数大小如 mov [rdi], ax
将具有与 66
操作数大小前缀相同的机器代码。
8 位操作数大小 (mov [rdi], al
) 有自己的操作码,不需要前缀。
movzx
/ movsx
是有趣的情况:内存访问大小与目标寄存器不同。内存访问大小(字节或字)由操作码指定。操作数大小前缀只影响目标大小。 x86-64 63 /r
movsxd
(双字->qword 符号扩展)除外,其中 66
操作数大小前缀 会 缩小内存访问缩小到 m16
以匹配目的地。
SIMD 指令类似;指令编码唯一地确定内存访问大小,以及读取或写入的寄存器。