【问题标题】:Result of storing a value larger than 8 bits into an 8 bit register将大于 8 位的值存储到 8 位寄存器的结果
【发布时间】:2019-07-04 15:05:33
【问题描述】:

我想知道当您尝试将对于 8 位寄存器来说太大的值存储到 8 位寄存器中时会发生什么。

高 8 位会发生什么?这些数据是丢失了,还是例如转移到 bx 中? mov 指令是否关心,或者它只是将 00ffh 存储到 al 中?

例子:

xor bl,bl
add bl,0fffh
mov al,bl

【问题讨论】:

  • 理想情况下,汇编器会阻止您这样做,因为它是不可编码的指令。
  • add bl,ffffh 不存在
  • 它是不可编码的,但是已知一些汇编程序会通过警告将其截断为所需的大小,而有些汇编程序会以静默方式进行。大多数汇编程序会产生一个硬错误。啊,我看到你正在使用 NASM。 NASM 默认发出警告。它所做的是将 0ffffh 截断为低位 0ffh 并将其存储在 8 位寄存器中。
  • 为了清楚起见,cpu 永远不会看到你的常量太大,所以它不是 mov 指令在运行时做一些魔术。
  • 显然您使用的 NASM 版本将其视为默认警告。您可以通过与-Werror=number-overflow(或简单的-Werror)组合将其视为错误。

标签: assembly x86


【解决方案1】:

add bl, 0xff 的截断发生在汇编时。(或者,如果您使用 NASM -Werror=number-overflow-Werror,则会收到汇编时错误)

x86 机器码没有立即数大于操作数大小的编码;这将是多余的并且浪费空间。例如add r/m8, imm16 不存在,只有 imm8。有关可用编码,请参阅 https://www.felixcloutier.com/x86/add

如果您想将其视为符号扩展至 32 位,然后截断至目标宽度,那很好,因为它不会改变结果。但这样的心理体操可能没有帮助。

指令的操作数大小设置为 8 位,目的寄存器是 asm 源中的 8 位寄存器。所以汇编器会选择 8 位的add 操作码。因此,当 CPU 对其进行解码时,操作数大小由操作码设置,而不是由立即数或加法结果设置。

mov 指令是否关心,或者它只是将 00ffh 存储到 al 中?

我可以看出您如何想象add 可能会扩大并影响 BH,但我不明白这会有什么任何意义。

这是一个单独的指令。

这是汇编语言;每条指令都是单独组装的,并且(逻辑上)按程序顺序单独运行,对机器的架构状态产生特定的影响。

(真正的 x86 CPU 执行并行/乱序执行,但会跟踪所有内容以保持指令一次按顺序运行的错觉。这是 C/C++ 的硬件等价物“as-if "规则。)

【讨论】:

  • 谢谢彼得,我很感激你的洞察力。
猜你喜欢
  • 2020-11-21
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
  • 2017-07-12
  • 2017-04-14
相关资源
最近更新 更多