从内存中的数据设置 x86 部分寄存器(EAX、AX、AH)

x86 partial registers (EAX, AX, AH) being set from data in memory

我在汇编编程中的理解:

EAX : 22 66 77 55
 AX :       77 55
 AH :       77
 AL :          55

但是我真的不明白从带有指针偏移量的数组中读取数据时它是如何工作的:

 .data 
 arrayW WORD 1233h,2245h, 1176h

 ptr2 PWORD arrayW

 .code 
    mov esi, ptr2
    mov ax, [esi]
    mov ah, [esi + 1]
    mov ax, [esi + 2]
    mov eax, [esi + 2]

mov ax, [esi] 寄存器 EAX = 12331233。我以为寄存器 EAX 会是 00001233?

还有,mov ax,[esi + 2]寄存器=EAX=12334455,不明白寄存器怎么变成12334455。

有人可以向我解释一下执行后寄存器的所有值是什么吗?

请参阅 Assembly programming memory Allocating EAX vs Ax, AH, AL 了解 AX、AH 和 AL 作为 EAX 的子集如何重叠。

写入部分寄存器(AX、AH 或 AL)不会修改 EAX 的其余部分。 (在 64 位模式下,writing EAX does zero the upper half of RAX

所以mov ax, [esi]保留EAX的前2个字节不变,并用AX=0x1233替换低2个字节。这意味着 AH=0x12 和 AL=0x33,并且 EAX=0x22 66 12 33.


内存中的字节是小端,所以mov ah, [esi + 1]加载0x12([=13=的高字节,数组的第一个字。)

这是汇编语言。一切都只是字节。他们按顺序到达那里并不重要,因为您使用 WORD 1233h,2245h 而不是 BYTE 33h,12h, 45h, 22h。 CPU 不知道也不关心指令的任何 "meaning",它只是从 [esi+1] 加载 1 个字节,并将其放入 AH。 (已经有来自 mov ax, [esi] 的那个值)。

寄存器中的字节没有字节序,因为它们没有地址。左移总是乘以 2,右移总是除以 2(向 -Infinity 舍入,与有符号整数除法不同)。


另请参阅 标签 wiki,了解更多常见问题以及指向文档和指南的链接。

您始终可以将此代码放入程序中,然后 运行 将其放入调试器中以在您单步执行它时观察寄存器值的变化。如果您不确定会发生什么,请执行此操作。


顺便说一句,mov esi, ptr2 很傻。 mov esi, offset arrayW 不需要从数据存储器加载指针就可以做同样的事情。