从内存中的数据设置 x86 部分寄存器(EAX、AX、AH)
Posted
技术标签:
【中文标题】从内存中的数据设置 x86 部分寄存器(EAX、AX、AH)【英文标题】:x86 partial registers (EAX, AX, AH) being set from data in memory 【发布时间】:2016-09-26 01:11:20 【问题描述】:在汇编编程中我理解:
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 language - Why are characters stored in register as little endian? 【参考方案1】:请参阅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 个字节不变,并将低 2 个字节替换为 AX=0x1233。这意味着 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(向 -Infinity 舍入,与有符号整数除法不同)。
另请参阅x86 标签 wiki,了解更多常见问题解答以及文档和指南的链接。
您始终可以将此代码放入程序中并在调试器中运行,以观察寄存器值在您单步执行时的变化。如果您不确定会发生什么,请执行此操作。
顺便说一句,mov esi, ptr2
很傻。 mov esi, offset arrayW
会做同样的事情,而不需要从数据内存中加载指针。
【讨论】:
'mov ah, [esi+1]' 执行后寄存器的值有变化吗?因为它是 WORD 所以 [esi+1] 不指向任何东西对吗? [esi+2] 指向第二个元素? @student001:这是汇编语言。一切都只是字节。他们按那个顺序到达那里并不重要,因为您使用了WORD 1233h,2245h
而不是BYTE 33h,12h, 45h, 22h
。 CPU 不知道也不关心指令的任何“含义”,它只是从 [esi+1]
加载 1 个字节。
对不起,我是新手。但我只是想确保我理解。因此,如果我使用 DWORD 12344h
= BYTE 44h, 23h, 01h
。是对的吗?还有一个,BYTE 1,2,3,4
= WORD 4321h
?
@student001:是的,但是您遗漏了第 4 个字节 (00h
)。 DWORD 始终为 4 个字节,并且不依赖于常量的大小。 (它代表双字)。 en.wikipedia.org/wiki/Endianness有一些图片。以上是关于从内存中的数据设置 x86 部分寄存器(EAX、AX、AH)的主要内容,如果未能解决你的问题,请参考以下文章