X86 英特尔xed解码指令不';t完全匹配8086汇编代码

X86 英特尔xed解码指令不';t完全匹配8086汇编代码,x86,intel,disassembly,machine-code,xed,X86,Intel,Disassembly,Machine Code,Xed,我玩了一点xed,目的是编写一个英特尔8086的小型模拟器,我想使用xed作为解码器。但是当我在asm中编写一些代码(用nasm编译)时: 并尝试展示一些东西,看看是否理解xed的工作原理,我有以下行为: 0x0:0x0 (0x0) MOV : length = 2 operand0: AL (REG0) operand1: 7f (IMM0) 0x0:0x2 (0x2) XOR : length = 3 operand0: BX (REG0) operand1: BX (REG1) oper

我玩了一点xed,目的是编写一个英特尔8086的小型模拟器,我想使用xed作为解码器。但是当我在asm中编写一些代码(用nasm编译)时:

并尝试展示一些东西,看看是否理解xed的工作原理,我有以下行为:

0x0:0x0 (0x0)
MOV : length = 2
operand0: AL (REG0)
operand1: 7f (IMM0)

0x0:0x2 (0x2)
XOR : length = 3
operand0: BX (REG0)
operand1: BX (REG1)
operand2: (REG2)

0x0:0x5 (0x5)
XCHG : length = 3
operand0: BX (REG0)
operand1: BX (REG1)

0x0:0x8 (0x8)
CLI : length = 1
operand0: EFLAGS (REG0)

0x0:0x9 (0x9)
HLT : length = 1
我不明白为什么xor有3个操作数,cli有1个操作数,一般来说,在很多情况下,显示的操作数与intel指定的操作数不匹配。我做错了什么

这是我在a中使用的代码(我尽了最大努力使其尽可能少)


[编辑]

现在事情有点清楚了:我用
nasm-f bin test.s
编译了
xor bx,bx
,我的程序告诉我:

0x0:0x0 (0x0)
XOR : length = 2
operand0: BX (REG0)
operand1: BX (REG1)
operand2: FLAGS (REG2)
xor的长度是2:没错,我们处于16位模式。 有两个显式操作数:bx和bx对 有一个隐式禁止的操作数:flags(如@Peter Corde said)


现在一切看起来都很好

CLI清除EFLAGS中的IF位,因此这是有意义的

看起来XED包含隐式操作数,而不仅仅是在机器代码中显式的操作数。i、 e.对体系结构状态的所有更改

XOR写标志,但XCHG不写。所以REG2可能是EFLAGS。但是您的代码在
switch
语句中只有
case-XED\u-OPERAND\u-REG0
…REG1
,因此它可能有一个名称(可能是EFLAGS),但您的代码选择不打印它


我很好奇,所以我为您阅读了XED文档:根据它们的可见性:要么显式(如
xor bx,bx
)要么隐式,要么“隐式抑制(
SUPP
)”。SUPP操作数是:

SUPP操作数是:

  • 不用于选择编码(这是与普通隐式的区别)
  • 未在拆解中打印
  • 未在编码中使用操作数位表示
因此,您应该检查
xed_操作数\u可见性\u枚举\t
,只打印显式操作数


顺便说一句,您似乎已经在32位或64位模式下组装了代码,因为像
xor bx,bx
这样的16位指令有3个字节长。在16位模式下,它将只是操作码+modrm。汇编程序(并由反汇编程序正确解码)添加的操作数大小前缀(
66
)可以解释这一点


[CPU 8086]
并不意味着
[BITS 16]
。除非出于某种原因您确实需要16位模式,否则您可能应该继续使用32位模式。(您的反汇编程序已在以汇编程序所用的相同模式对其进行解码。使用
位16
将允许您将16位机器代码放入32位对象文件中,这只会使其解码错误。

CLI清除EFLAGS中的IF位,因此这是有意义的

似乎XED包含隐式操作数,而不仅仅是在机器代码中显式的操作数。即,对体系结构状态的所有更改

XOR写标志,但XCHG不写。所以REG2可能是EFLAGS。但是您的代码在
switch
语句中只有
大小写x\u操作数\u REG0
…REG1
,所以它可能有一个名称(可能是EFLAGS),但您的代码选择不打印它


我很好奇,所以我为您阅读了XED文档:根据它们的可见性:显式(如
xor bx,bx
)或隐式,或“隐式抑制(
SUPP
)”。SUPP操作数是:

SUPP操作数是:

  • 不用于选择编码(这是与普通隐式的区别)
  • 未在拆解中打印
  • 未在编码中使用操作数位表示
因此,您应该检查
xed_操作数\u可见性\u枚举\t
,只打印显式操作数


顺便说一句,您似乎已经在32位或64位模式下组装了代码,因为您的16位指令(如
xor bx,bx
)有3个字节长。在16位模式下,它将只是操作码+模式。由汇编程序添加(并由反汇编程序正确解码)的操作数大小前缀(
66
)可以解释这一点


[CPU 8086]
并不意味着
[BITS 16]
。除非出于某种原因确实需要16位模式,否则您可能应该继续使用32位模式。(你的反汇编程序已经在以你的汇编程序正在汇编的相同模式对其进行解码。使用
位16
会让你将16位机器代码放入32位对象文件中,这只会使它解码错误。

我在asm文件中使用[bit 32]而不是[CPU 8086]时得到了相同的结果@阿德里安:当然可以。
xor bx,bx
在32位模式下需要
66
前缀,但在
位16
中不需要。我猜在汇编程序中,设置
[CPU 8086]
不会设置
[BITS 16]
。无论如何,除非您的对象文件格式可以表示,否则您可能不需要
位16
。将16位机器代码放入32位对象文件只会使其解码错误。(例如,作为
异或ebx,ebx
)@Adrien关于XOR,EFALGS寄存器对应于
XED\u OPERAND\u REG2
,您的代码不会在switch语句中打印它。因此,您最终只打印
(REG2)
part@PeterCordes我正在创建一个原始二进制文件格式。这个项目是为了在学校做演示,所以也许我应该尝试一些更简单的方法,因为据我所知,我的问题是我试图用386+?@HadiBrais的规则对英特尔8086的指令进行编码,但问题是xor应该只有2个操作数,不是三个当我在asm文件中使用[BIT 32]而不是[CPU 8086]时,我得到了相同的结果@Adrien:当然可以。
xor bx,bx
需要在32位模式下使用
66
前缀,但在
位模式下不需要
0x0:0x0 (0x0)
XOR : length = 2
operand0: BX (REG0)
operand1: BX (REG1)
operand2: FLAGS (REG2)