【问题标题】:Move smaller operand into larger operand将较小的操作数移动到较大的操作数
【发布时间】:2018-07-05 02:42:36
【问题描述】:

我在想象数据如何进入 RAX 寄存器时遇到了一些麻烦。

这里是汇编语言:

.data
dwordVal DWORD 94326732h
.code
mov rax, 0FFFFFFFF00000000h
mov rax, dwordVal

我了解到您无法使用 MOV 将较小的操作数移动到较大的操作数中。在我看来,dwordVal 只会填充 64 位 rax 寄存器的下半部分,所以这是不允许的。如果我错了,请纠正我。

【问题讨论】:

  • 如果您使用的汇编程序将dwordVal 视为内存引用,那么mov 将无意识地加载 64 位,即使您只定义了 32 位数据。如果您的汇编程序将其用作地址,那么当然你只是加载一个 64 位地址就可以了。
  • 所以第一个 mov 操作初始化 rax 寄存器,如果我理解正确,第二个 mov 填充下半部分
  • 你应该经常在调试器中尝试这些东西。例如,如果您要定义dwordVal DWORD 94326732h, 0deadf00dh 并执行mov rax, dwordVal,则根据您的汇编程序,rax 将包含94326732h 值的第一个字节的地址,或来自内存0deadf00d94326732h 的qword 值(两个双字都已加载),两者都明显不同意你最初的想法。在单步执行指令时在调试器中观察事物通常是最好的第二知识来源(在阅读指令参考指南中的纯理论之后)。

标签: assembly x86-64 cpu-registers


【解决方案1】:

mov 指令将始终使用与目标操作数大小完全相同的完整值填充目标操作数。

所以,你的理解是错误的。您不能用mov 填充rax 的一部分。

正如 Jester 在评论中已经说过的那样,mov rax, dwordVal 的结果究竟会发生什么取决于您的汇编程序遵循的约定,并且某些汇编程序实际上会拒绝这种非法行为。

我可以告诉你的一件事是,之前加载到其中的 0FFFFFFFF00000000h 绝对不会在 rax 中留下任何东西。

【讨论】:

  • 好吧,您可以用mov 填充rax 的一部分,例如mov ax,1mov al,1mov ah,1 等。但是只有 rax 的低 16 位可用于此类修改(并且通常会在性能方面受到惩罚,为了使代码通常更快,应该先将两个值加载到 64b 寄存器中,然后与 @987654333 合并@ 或 add 指令)。 mov eax,1 也会清除高 32 位,所以初始化完整的 rax
猜你喜欢
  • 2019-04-04
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 2014-12-09
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
相关资源
最近更新 更多