经典变长指令_Reg/Opcode

 

 

 在之前的课程中,3-5位用来标识寄存器,Mod字段 与 R/M字段共同用来标识寄存器与内存

但3-5字段,并不仅仅用来标识寄存器,有些时候,用来标识Opcode

参见Table A-2中 :

 

80 81 82 83 这几个编码,并没有明确给出具体的操作码是什么。

 

 有这个Grap字段的都去看TableA-6

 

 

 举例说明:

80 65 08 FF

查表步骤:

1、第一个字节为80 查TableA-2表,得到对应结构:Eb,Ib

 

 

 

2、第二个字节为ModR/M字段,所以拆分65:

01 100 101

Mod 与 R/M字段 查Table2-2 得到对应的结构:[EBP+DIS8]

 

 

 

3、100 字段 查表TableA-6 得到对应操作码为:AND

 

 

 

4、最终的指令格式:

AND [ebp+dis8],Ib

AND BYTE PTR SS:[EBP+08],0xFF

指令前缀

 

 

 1、段前缀:

段寄存器的作用:早期8086cpu寻址范围小,Inter遍通过段寄存器来拓展内存.即通过段寄存器基址+偏移的方式来寻址。

[]中的地址为有效地址(Effect Address),有效地址+段寄存器基址才是实际地址LA(线性地址 Line Address)。

线性地址 = 段基址 + 有效地址

在后来的80386时,cpu的寻址范围大大提升,这些段寄存器便被用作了其他用途。但是DS:[]类似

这种寻址格式却被保留了下来。

实际上操作码已经决定了寻址时使用哪个段寄存器作为基址,不需要其他字节描述。

1、如果没有特别说明,[]前为DS,即DS:[]

2、PUSH POP指令,以及在[]中使用ESP/EBP的,使用SS段

3、在[Base + Index*2Scale + I]中,以Base为判断条件,没有特别说明,用DS。如果Base为ESP/EBP,则用SS段.

4、串操作指令一般使用ES。MOV ES:[EDI] DS:[ESI]中,目标EDI使用ES段,其他使用DS段.

5、EIP指向当前指令,EIP取指令时使用的是CS段.

6、如果指令加段寄存器前缀,则该条指令一律用这个段,如果加多个段寄存器前缀,默认只看op前的那个.

2、操作指令前缀

0x66 将操作数改为16字节。例子50为 PUSH EAX, 而66 50则为 PUSH AX

004183DA      50                     PUSH EAX

004183DB      66:50                  PUSH AX

3、操作指令前缀:修改默认寻址方式

0x67 将操作数改为16字节。例子50为 PUSH EAX, 而66 50则为 PUSH AX

004183FD      8801          MOV BYTE PTR DS:[ECX],AL

004183FF      67:8801       MOV BYTE PTR DS:[BX+DI],AL

 

硬编码总结

1、操作码决定后面有没有ModR/M字段和立即数
2、ModR/M决定后面有没有SIB字节和偏移
3、操作指令中只要包含Ev/Eb,则指令中一定有ModR/M字节
4、只需要把操作码确定下来,那么后面有什么字段,就都能确定了。即一切由操作码决定。
5、操作码长度
一个字节:00-FF(TableA-2    0F除外)
两个字节:OF 00 - OF FF(TableA-3)
三个字节:OF 38 / OF 3A (TableA-3 TableA-4 TableA-5)
6、其他。。。 。 。 。 。 。 。 。 。 。

 

说明

转滴水三期课件

posted @ 2021-04-10 17:16  Punished  阅读(321)  评论(0编辑  收藏  举报