如何让 NASM 使用符号扩展的 16 位立即数对推送进行编码?

问题描述 投票:0回答:1

使用 nasm 组装以下内容时:

BITS 64
push 32767

我明白

68 ff 7f 00 00
这对我来说很有趣,因为这是 32b 编码(push dword) - 有什么想法为什么它不诉诸 16b 编码(这会更短,并且使用更少的堆栈内存)?

我尝试过各种立即数组合,但它似乎从未使用 16b 编码。

assembly x86-64 nasm instruction-encoding immediate-operand
1个回答
1
投票

16 位立即数仅适用于 16 位操作数大小。

RSP -= 2
并进行 2 字节存储:
push word 0x7fff
)。

与大多数 x86 指令(例如

add
)一样,没有
sign_extended_imm16
编码。 (
push
和其他堆栈操作的特殊之处在于,在 64 位模式下默认操作数大小为 64,即使使用 REX 前缀也无法覆盖为 32。与其他操作码默认为 32,使用 64 位编码与 REX.W)。

在没有操作数大小前缀来指定 16 位操作数大小的 32 和 64 位模式下,立即数为符号扩展 8 或 32 位(如果操作数大小为 32 位,则为符号扩展)。 这适用于所有普通操作码;有一些特殊情况,例如

mov r64, imm64
enter imm16,imm8

在 NASM 中,

push 1234
默认为
push qword 1234
,而不是
push word 1234
,因为那是人们通常想要的。 (请参阅当我不指定操作数大小时,推送指令会推送到堆栈上多少字节?不重复,因为我的答案 IIRC 没有详细说明
push imm16
仅存在于 16-位操作数大小。)


英特尔手册顶部的表格

push
(HTML 摘录:https://www.felixcloutier.com/x86/push)对此并不是很清楚,“描述”列没有提及操作数大小。 文字描述部分也没有提及。

68 iw
68 id
是相同的操作码,因此 CPU 知道您想要的唯一方法是通过操作数大小属性。 这以及编码操作数大小的一般规则(当前模式隐含的默认规则,可使用前缀覆盖)意味着无法对
68 iw
进行编码,使其符号扩展为更宽的宽度;当操作数大小为 16 位时,
68
仅采用
iw
(立即字)。

© www.soinside.com 2019 - 2024. All rights reserved.