【问题标题】:add 1 byte immediate value to a 2 bytes memory location将 1 字节立即值添加到 2 字节内存位置
【发布时间】:2017-12-18 20:15:56
【问题描述】:

this page 的 add 指令文档说明如下:

请注意我突出显示的两条说明。

我在 NASM 中尝试了以下代码(符合第一个突出显示的指令):

add WORD [myvar], BYTE 0xA5

但我收到以下错误:

警告:有符号字节值超出范围

我做错了什么?

【问题讨论】:

  • 如果你尝试 -91 而不是 0xA5 会怎样?
  • 或者你想添加+165?
  • @old_timer add WORD [myvar], BYTE -91 有效,但 add WORD [myvar], BYTE 165 doesn't work.
  • 你想做什么 -91 或 +165?如果是 +165,那么 fuz 回答了你的问题,并且已经说过字节 165 不起作用。但是,如果您没有尝试 +165 而是 -91 则使用 -91 而不是 0xA5 并且 fuz 仅部分回答了您的问题。

标签: assembly x86 nasm


【解决方案1】:

8 位立即数操作数(此处用 imm8 表示)符号扩展为 16(或 32)位,以匹配另一个操作数(分别为 r/m16 或 r/m32)的大小。

因此,只能表示 -128 和 127 之间的值,这就是您从汇编程序收到此警告的原因。

对于值 0xA5,您需要使用 WORD 立即数 (imm16):

add WORD [myvar], WORD 0xA5

(尽管WORD 在源操作数上是可选的,因为它是由常量的大小暗示的)。

【讨论】:

  • 最好让汇编程序为您选择立即数的宽度,并在有歧义时将操作数大小说明符放在内存操作数上。
【解决方案2】:

我不会重复@fuz的回答,但我想补充一下:

如果您只是让汇编器通过编写add word [myvar], 0xA5 来完成它的工作,那么它会选择最小的有效编码。如果您的立即数适合符号扩展的 imm8,它将使用 add r/m16, imm8 编码。通常不需要对非内存操作数使用大小覆盖。所有主要的 x86 汇编器都优化了立即操作数的大小。有些(例如 NASM)甚至会将 mov rax, 1 优化为等效但更短的 mov eax, 1 和类似的东西,但其他 (YASM) 不会。

不过,您可以强制汇编器使用比填充/对齐所需的更宽的立即数。例如add word [myvar], strict word 1。将使用imm16 版本。 (没有strict,它不会阻止汇编器将其优化为更小的编码。)您还可以add word [rcx + strict dword 0], strict word 1 强制为寻址模式使用[base + disp32] 编码。


如果可能,避免将 16 位立即操作数用于除 mov 之外的指令。在许多 Intel CPU 上,由于an LCP stall,该指令的解码速度会很慢。在具有解码的微指令缓存的较新 CPU 上,这可能不是问题。但在较旧的 Intel CPU 上,这可能会运行得更快,但代价是暂存寄存器:

movzx  eax, word [myvar]
add    eax, 0xA5          # add ax, 0xa5 is 1B smaller, but has the same LCP stall.
mov    [myvar], ax

add/sub 从左到右进行,因此较宽添加的低部分始终与您从窄 add 中得到的相同。避免寄存器操作数的 LCP 停顿通常很便宜(add eax,imm32 只需额外的 1B,因为它不需要操作数大小的前缀),但加载和存储是额外的。

这是更多的代码大小,因此在没有 LCP 停顿的 CPU 上可能会更慢。英特尔 Sandybridge 系列的前端仅多 1 个微指令(可以在单指令版本中微融合加载+添加),而执行单元/调度程序的微指令数量相同。 (内存目标指令解码以加载、ALU 和存储微指令。)

【讨论】:

  • (另一个选项是mov eax, 0xa5 / add [myvar], ax,但在现代英特尔上,后端的微指令更多,而前端的总数相同:(1 + 2 = 3)。 memory-dst add 的 load+add 微熔丝,store-address+store-data uops 微熔丝,所以add [mem],reg 总共是 2 个前端 uops,4 个后端 uops。(相同的后端uops 作为 movzx 加载;添加 reg,imm;mov-store;并且不包括 mov-immediate。)
猜你喜欢
  • 2013-11-16
  • 2011-06-27
  • 2017-04-03
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 2019-07-19
  • 2021-06-14
  • 1970-01-01
相关资源
最近更新 更多