在汇编编程中,我理解:
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的。
有人可以向我解释执行后寄存器的所有值是什么吗?
答案 0 :(得分:4)
有关AX,AH和AL如何重叠的信息,请参阅Assembly programming memory Allocating EAX vs 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(0x1233
的高字节,即数组的第一个字。)
这是汇编语言。一切都只是字节。他们按顺序到达那里并不重要,因为您使用的是WORD 1233h,2245h
而不是BYTE 33h,12h, 45h, 22h
。 CPU不知道或不关心指令的任何“含义”,它只从[esi+1]
加载1个字节,并将其放入AH中。 (已经有mov ax, [esi]
的价值。
寄存器中的字节没有字节序,因为它们没有地址。左移总是乘以2,右移总是除以2(向无穷大舍入,与有符号整数除法不同)。
另请参阅x86代码维基以获取更多常见问题解答,以及指向文档和指南的链接。
您始终可以将此代码放入程序中并在调试器中运行,以便在单步执行时更改注册寄存器值。如果您不确定会发生什么,请执行此操作。
BTW,mov esi, ptr2
很愚蠢。 mov esi, offset arrayW
可以做同样的事情而无需从数据存储器加载指针。