为啥`add cl, 2`以x86 hex打印`80 c1 02`?

Posted

技术标签:

【中文标题】为啥`add cl, 2`以x86 hex打印`80 c1 02`?【英文标题】:Why does `add cl, 2` print `80 c1 02` in x86 hex?为什么`add cl, 2`以x86 hex打印`80 c1 02`? 【发布时间】:2021-01-28 01:39:20 【问题描述】:

试图缩小我的问题范围,以便我能够克服这个障碍。 This 对我帮助不大。

我正在运行 NASM 以查看程序集的输出以十六进制表示。

test:
    @nasm -f macho64 test.asm
    @objdump -x86-asm-syntax=intel --full-leading-addr -d test.o
.PHONY: test

我有一些东西,其中之一是:

add cl, 2

输出为:

80 c1 02

查看Intel Manuals,我转到添加部分,它显示如下:

80 /0 ib

看起来很接近,80 在那里,ib 是我的号码 2 即时值。但是如何从/0 中计算出这个c1

文档说:

/digit — 0 到 7 之间的数字表示指令的 ModR/M 字节仅使用 r/m(寄存器或内存)操作数。 reg 字段包含提供指令操作码扩展的数字。

我的问题是:

    为什么汇编器决定在这里放一个 ModR/M 字节? “仅使用 r/m(寄存器或内存)操作数”是什么意思?什么操作数,是说它承认有一个寄存器cl和一个立即数2,所以它选择cl,因为它是一个寄存器? “reg 字段包含提供指令操作码扩展的数字。”唔?这是什么意思?我只能从中收集到,/0 意味着它是第 0 个寄存器?但这行不通,似乎是错误的。 表 2-1 中有值c1,它与“有效地址”标题下的cl 寄存器对齐。虽然不知道那是什么意思。对应的 R/M 位就在001,它所在的列是0。虽然这些对我来说都没有多大意义。

我如何说服自己这个c1 字节是正确的?我如何阅读各种表格中的所有标志,我如何仅通过查看组件和 Intel 表格来自行推断?

【问题讨论】:

我应该链接How to determine if ModR/M is needed through Opcodes?,而不是x86_64 Opcode encoding formats in the intel manual。 vol.2 手册条目中的表格显示了哪个 asm 级操作数在机器代码的哪个部分精确编码。 回复:/0:How to read the Intel Opcode notation 的重复项(我的回答专门针对 /number 的含义,而不是 /r。) 【参考方案1】:
    因为80 /0 ibOp/En 表示MI,这表示Operand1 在MODRM:r/m 中。 这意味着它只使用 modr/m 的“r/m”部分而不是“reg”部分。 表示“reg”部分包含一个常量0 作为操作码扩展。 您查看 modr/m 表 2-2,它有一个标题行,上面写着“/digit (Opcode)”。因此,由于/0,您选择了0 列。然后选择ECX/CX/CL/MM1/XMM1 行,瞧,你得到了C1 值。

【讨论】:

好吧,第 4 点越来越清楚,但我还是不明白第 2 点和第 3 点。 见2.1章开头的图2-1。 modr/m 字节由 3 个字段组成,modreg/opcoder/m。一些指令使用reg 来编码一个额外的寄存器操作数,在你的情况下,其他指令使用它作为一个操作码扩展。 你怎么知道这个案例使用它作为操作码扩展? /0 的定义就是这个意思。请参阅第 3.1.1.1 节:"/digit 0 到 7 之间的数字表示指令的 ModR/M 字节仅使用 r/m(寄存器或内存)操作数。reg 字段包含提供指令操作码的扩展。” 此外,从逻辑上讲,“reg”字段中没有要编码的内容 - 一个操作数来自 r/m,另一个是简单附加的立即字节。 @LancePollard: What does the /4 mean in FF /4? 和How to read the Intel Opcode notation 上的答案都引用了手册的那部分内容。我对最后一个问题的回答在不引用手册的情况下解释了这一切,因为另一个答案已经转储了该手册部分。所以这个信息已经在 Stack Overflow 上流传,供未来的读者在答案中找到,而不仅仅是 cmets。

以上是关于为啥`add cl, 2`以x86 hex打印`80 c1 02`?的主要内容,如果未能解决你的问题,请参考以下文章

错误 MSB6006:“CL.exe”以代码 2 退出

为啥 CMake 似乎没有使用 add_compile_options 命令应用 -pthread?

内置函数:进制转换,bin,oct,hex

为啥 Hex() 函数返回一个字符串而不是一个 int hex?

在 x86 程序集中打印十六进制值

MASM x86 如何打印多行字符串变量?