为啥`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 ib
的Op/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 个字段组成,mod
、reg/opcode
和 r/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`?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 CMake 似乎没有使用 add_compile_options 命令应用 -pthread?