AX、AH、AL 如何映射到 EAX?
Posted
技术标签:
【中文标题】AX、AH、AL 如何映射到 EAX?【英文标题】:How do AX, AH, AL map onto EAX? 【发布时间】:2022-01-19 11:31:01 【问题描述】:我对 x86 寄存器的理解是说每个寄存器都可以被整个 32 位代码访问,并且分成多个可访问的寄存器。
在这个例子中EAX
是一个32位寄存器,如果我们调用AX
它应该返回前16位,如果我们调用AH
或AL
它应该返回16之后的下8位bits 和 AL
应该返回最后 8 位。
所以我的问题是,因为我并不真正相信这就是它的运作方式。如果我们存储 32 位值,也就是 EAX
存储:
0000 0100 0000 1000 0110 0000 0000 0111
所以如果我们访问AX
它应该返回
0000 0100 0000 1000
如果我们读到AH
它应该返回
0000 0100
当我们读到AL
它应该返回
0000 0111
这是正确的吗?如果是 AH
真正具有什么价值?
【问题讨论】:
不,您的 AX 值是错误的。破解最后 16 位。 AH 只返回 EAX 的第 8 位到第 15 位。 请将位模式替换为在您的问题上下文中更容易理解的内容,例如:0000 0001 0010 0011 ... 相关:Assembly language - Why are characters stored in register as little endian? re:映射到内存。 【参考方案1】:不,这不太对。
EAX is the full 32-bit value
AX is the lower 16-bits
AL is the lower 8 bits
AH is the bits 8 through 15 (zero-based)
所以 AX 由 AH:AL 两半组成,它本身就是 EAX 的低半。 (EAX 的上半部分不能作为 16 位寄存器直接访问;如果需要,可以移位或旋转 EAX。)
为了完整起见,除了上述基于 32 位 CPU 的内容外,64 位 Intel/AMD CPU 也有
RAX, which hold a 64-bit value, and where EAX is mapped to the lower 32 bits.
所有这些也适用于 EBX/RBX、ECX/RCX 和 EDX/RDX。其他寄存器如 EDI/RDI 有 DI 低 16 位部分寄存器,但没有高 8 部分,低 8 DIL 只能在 64 位模式下访问:Assembly registers in 64-bit architecture
由于历史原因,写入 AL、AH 或 AX 会在完整的 AX/EAX/RAX 中保留未修改的其他字节。例如,它必须将一个新的 AL 合并到完整的 RAX 中。 (在 32 位或 64 位代码中,如果您不特别希望这种合并,请首选 movzx eax, byte [mem]
或 movzx eax, word [mem]
加载:Why doesn't GCC use partial registers?)
将 EAX 零扩展写入 RAX。 (Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?)
同样,所有这些都适用于每个寄存器,而不仅仅是 RAX。例如写入 DI 或 DIL 会合并到旧 RDI,写入 EDI 零扩展并覆盖整个 RDI。对于 R10B 或 R10W 写入合并相同,写入 R10D 使 R10 独立于旧 R10 值。
【讨论】:
所以你会说我的误解来自 Ax 是前 16 名,而是调用了一个同时包含 Al 和 Ah 的值? 感谢您的帮助,这一切都清楚了。这么愚蠢的错误 如何称呼高 16 位和高 32 位?是否有 EAXH 或 AXH? @user97662:不,没有办法只访问寄存器的上部 - 您必须读取整个寄存器并根据需要进行移位。 感谢 Peter Cordes 大力扩充这个答案。【参考方案2】:AX 是 EAX 的低 16 位。 AH 是 AX 的高 8 位(即 EAX 的 8-15 位),AL 是 EAX 和 AX 的最低有效字节(0-7 位)。
示例(十六进制数字):
EAX: 12 34 56 78
AX: 56 78
AH: 56
AL: 78
【讨论】:
【参考方案3】:| 0000 0001 0010 0011 0100 0101 0110 0111 | ------> EAX
| 0100 0101 0110 0111 | ------> AX
| 0110 0111 | ------> AL
| 0100 0101 | ------> AH
【讨论】:
您应该删除手动空格( 
),并将整个内容格式化为代码块(每行缩进 4 个空格,它将采用单空格格式,并保留间距)【参考方案4】:
不,你的答案是错误的
Al 和 Ah 的选择来自 AX 而不是来自 EAX
例如
EAX=0000 0000 0000 0000 0000 0000 0000 0111
所以如果我们调用 AX 它应该返回
0000 0000 0000 0111
如果我们调用 AH 它应该返回
0000 0000
当我们调用 AL 时它应该返回
0000 0111
示例编号 2
EAX: 22 33 55 77
AX: 55 77
AH: 55
AL: 77
示例 3
EAX: 1111 0000 0000 0000 0000 0000 0000 0111
AX= 0000 0000 0000 0111
AH= 0000 0000
AL= 0000 0111
【讨论】:
字节序有什么关系吗?如果我用GAS 组装movl $0x01 %eax
,%ax
和%al
的值是什么?一还是零?
@FrozenFlame:不,字节序仅适用于内存(包括mov $imm32, %eax
指令的编码方式,如opcode 01 00 00 00
。)。 %al 中的值将是 1
。如果您认为寄存器内的 MSB 位于左侧,LSB 位于右侧,则左移 %eax 会起作用。 (这对于向量寄存器可能会很棘手,请参阅***.com/questions/41351087/…)【参考方案5】:
否 -- AL 是 AX 的 8 个最低有效位。 AX 是 EAX 的 16 个最低有效位。
如果我们从 eax 中的 04030201h 开始,也许最容易处理。在这种情况下,AX 将包含 0201h,AH 将包含 02h,AL 将包含 01h。
【讨论】:
【参考方案6】:下面的 sn-p 使用 GDB 检查 EAX。
(gdb) info register eax
eax 0xaa55 43605
(gdb) info register ax
ax 0xaa55 -21931
(gdb) info register ah
ah 0xaa -86
(gdb) info register al
al 0x55 85
-
EAX - 完整的 32 位值
AX - 低 16 位值
AH - 8 到 15 位
AL - EAX/AX 的低 8 位
【讨论】:
您也可以在 gdb 中使用p /x $eax
打印寄存器(或省略 /x
以表示十进制)。并使用set $eax = 0xdeadbeef
, IIRC 修改它们。另请参阅x86 tag wiki 的底部以获取一些关于 asm 的 gdb 技巧。以上是关于AX、AH、AL 如何映射到 EAX?的主要内容,如果未能解决你的问题,请参考以下文章
x86_64寄存器rax/eax/ax/al覆盖完整的寄存器内容[重复]