【发布时间】:2023-03-14 08:18:01
【问题描述】:
我是第一次尝试组装的新手程序员。如果这是一个非常蹩脚的问题,请提前道歉。
我在 EAX 寄存器中存储了一个字符,但我需要将它移动到我的 DL 寄存器中。当我尝试: mov dl, eax 我收到错误 C2443:操作数大小冲突。我知道 eax 寄存器是 32 位的,而 dl 是 8 位的……我在做什么吗?我该如何解决这个问题。
【问题讨论】:
我是第一次尝试组装的新手程序员。如果这是一个非常蹩脚的问题,请提前道歉。
我在 EAX 寄存器中存储了一个字符,但我需要将它移动到我的 DL 寄存器中。当我尝试: mov dl, eax 我收到错误 C2443:操作数大小冲突。我知道 eax 寄存器是 32 位的,而 dl 是 8 位的……我在做什么吗?我该如何解决这个问题。
【问题讨论】:
你想要的大概是:
movzx edx, al
这会将 al 复制到 dl 并将 edx 的其余部分填充为零。这条指令相当于这两条指令:
xor edx, edx
mov dl, al
【讨论】:
movzx / movsx 可以使用内存源操作数,用于字节或字在内存中的其他用例。
试试
xor edx,edx
mov dl, al
也许?将 edx 的“不必要的”高位清零的第一条指令(可选),然后将低 8 从 eax 移动到 edx。
正如其他人所指出的,movzx 是一步完成的。值得一提的是,如果你在 al 中有一个 signed 值,你可以使用 "movsx edx, al" 用 al 的 msb 的副本填充 edx 的高位,从而将 al 的有符号 32 位表示形式放入 edx。
【讨论】:
xor edx,edx 不会将 %edx 中的所有位清零吗?
如果你只想访问 eax 的低 8 位,那么使用 al:
mov dl, al
您可以通过更改开头或结尾的字母来访问每个通用寄存器的低 8 位、16 位或 32 位。对于寄存器 eax,使用 eax 表示使用所有 32 位,ax 是低 16 位,al 是低 8 位。 ebx 的等价物分别是 ebx、bx 和 bl,依此类推。
请注意,如果您修改寄存器的低 16 位或 8 位,则高位不会改变。例如,如果你在 eax 中加载所有 1,然后将 0 加载到 al 中,那么 eax 的低 8 位将是 0,而高 24 位将是 1。
mov eax, -1 ; eax is all ones
mov al, 0 ; higher 24 bits are ones, lower 8 bits are zeros
【讨论】:
movzx edx, al 比使用 mov dl, al 合并到 EDX 的旧值中更有效。在 IvyBridge 之后的 Intel CPU 上,它可以从 mov-elimination 中受益并以零延迟运行。请参阅 Can x86's MOV really be "free"? Why can't I reproduce this at all? 和 Why doesn't GCC use partial registers?。在 AMD CPU 上,它只是避免了错误的依赖,即使您只计划在 DL 上使用 8 位操作数大小,这仍然很好。