将大寄存器移入小内存

时间:2018-03-11 09:24:02

标签: assembly x86 masm

我对PTR运算符有一点问题,我可以轻松地将大内存转移到下面的小寄存器示例中:

ax = small register which is 2 byte
memory = variable which is 4 byte


.data
variable dword 05010h

.code
mov ax,WORD PTR variable

它会正常工作。 现在我的问题是我不明白为什么我不能将像eax这样的大寄存器移动到一个2字节的小内存变量中?

示例:

.data
variable word ?

.code

mov eax, 01050h
mov variable, word ptr eax

说:Error invalid use of register

注意:如果大小匹配,它可以正常工作

1 个答案:

答案 0 :(得分:2)

问题是你显然不知道以下指令的作用:

mov ax, word ptr variable

该指令读取32位变量并将变量写入16位寄存器!

但是它做了什么?

通常,CPU不知道哪个数据类型存储在某个内存位置。地址variable的内存可能包含以下字节:

01h 02h 03h 04h

这可以是四个8位变量,两个16位变量(值为201h和403h),一个32位变量,值为4030201h,甚至一个16位和两个8位变量。

因为CPU不知道哪种变量存储在内存中,所以由程序员(或编译器)以16位变量的方式编写汇编程序被访问为16位变量。

指令mov ax, variable表示:"位置(地址)variable的RAM中有一个16位变量。读取它并将其写入ax寄存器。"

CPU会这样做。因为内存中包含字节01h 02h 03h 04h,所以它将读取两个字节01h 02h并将它们解释为16位变量(值为201h)。

使用所谓的" little-endian" CPU(如x86)这将导致"正确"当32位变量具有"小"值,因为该指令将有效地读取32位变量的低16位。

顺便说一句:使用" big-endian" CPU(如PowerPC)即使这样也不会再工作了,因为32位变量的高位(而不是低位)将被读取。

当然,您也可以将包含16位变量的存储单元读入32位寄存器:

mov eax, variable

让我们在上面的示例中说01h 02h 03h 04h是两个16位变量,其值为201h和403h。如果您将此RAM存储器读取为32位值,则结果为4030201h,而不是201h!

x86 CPU(自80386起)有两条指令movsx(符号扩展高位)和movzx(将高位设置为零),用于将较小的值复制到较大的寄存器中

这些说明可以让您正确地"将16位值读入32位寄存器。

修改

根据Peter Cordes的说法,MASM在dword ptr中明确要求mov eax, dword ptr variable,因为MASM将检查variable是否真的是32位并打印错误消息。

对于CPU,指令mov eax, variablemov eax, dword ptr variable的指令完全相同。

mov variable, word ptr eax
     

它说:Error invalid use of register

该指令可能(我不确定因为我不使用MASM)被命名为:

mov dword ptr variable, eax

但是你应该知道这条指令会做什么:它将覆盖内存中的32位:variable和内存中variable之后的数据。我怀疑这是你真正想做的事。

如果你想"转换"将32位值转换为16位值,如下面的C代码:

variable16 = (unsigned short)variable32;

......以下汇编代码将完成这项工作:

mov eax, variable32
mov variable16, ax

...因为axeax的低16位。