X64(64位)汇编指令与机器码转换原理


本文属于《 X86指令基础系列教程》之一,欢迎查看其它文章。

1 64位寻址形式下的ModR/M字节

x64指令机器码组成:
在这里插入图片描述
REX prefix组成:
在这里插入图片描述
ModR/M组成:
在这里插入图片描述

1.1 寻址方式

ModR/M字节具体值,组成情况,如下图所示:在这里插入图片描述
在这里插入图片描述
ModRM.mod、ModRM.r/m和REX.B三者确定一种寻址方式,一共有64种寻址方式。

1.2 寄存器编号

ModRM.reg与REX.R位,合并扩展为4位Rrrr,表示X64架构下这16个寄存器编号,具体编号如下:

r8(/r)
r16(/r)
r32(/r)
r64(/r)
mm(/r)
AL
AX
EAX
RAX
MM0
CL
CX
ECX
RCX
MM1
DL
DX
EDX
RDX
MM2
BL
BX
EBX
RBX
MM3
SPL
SP
ESP
RSP
MM4
BPL
BP
EBP
RBP
MM5
SIL
SI
ESI
RSI
MM6
DIL
DI
EDI
RDI
MM7
r8b
r8w
r8d
r8
r9b
r9w
r9d
r9
r10b
r10w
r10d
r10
r11b
r11w
r11d
r11
r12b
r12w
r12d
r12
r13b
r13w
r13d
r13
r14b
r14w
r14d
r14
r15b
r15w
r15d
r15
Rrrr0000000100100011010001010110011110001001101010111100110111101111

2 汇编指令转机器码

我们举几个立即数操作的例子:

mov cl, 12h
mov cx, 1234h
mov ecx, 12345678h
mov rcx, 1122334455667788h

然后,把表格中每一类寻址方式,都举一个例子,进行描述,如下:

序号寻址方式ModR/MREX.B汇编例子含义
1[r8]000001mov rcx,[r8]与mov [r8],rcx(rcx)=((r8))与((r8))=(rcx)
2[SIB]00100任意mov rcx,[r8+r9*2](rcx)=((r8)+(r9)*2)
3[disp32] / [rip+disp32]00101任意mov rcx,[00001000h](rcx)=(00001000h) / (rcx)=((rip)+00001000h)
4[r8+disp8]010001mov rcx,[r8+10h](rcx)=((r8)+10h)
5[SIB+disp8]01100任意mov rcx,[r8+r9*2+10h](rcx)=((r8)+(r9)*2+10h)
6[r8+disp32]100001mov rcx,[r8+00001000h](rcx)=((r8)+00001000h)
7[SIB+disp32]10100任意mov rcx,[r8+r9*2+00001000h](rcx)=((r8)+(r9)*2+00001000h)
8r8110001mov r9,r8(r9)=(r8)
9r9110011mov r8,r9(r8)=(r9)

因此,一共有13个汇编指令转机器码的例子,接下来,依次来讲解。

2.1 mov rcx, 1122334455667788h

  • mov cl, 12h
    mov cl, 12h表示将立即数12h存储到8位寄存器cl中。
    查询指令手册,与MOV r8,imm8指令相符,其操作码为B0+ rb,rb表示目的操作数cl寄存器编号。
    在这里插入图片描述
    当前指令cl编号为1,因此操作码为B0+1=B1。
    因此指令的机器码组成,如下所示:
汇编指令操作码立即数机器码
mov cl, 12hB112B112
  • mov cx, 1234h
    mov cx, 1234h表示将立即数1234h存储到16位寄存器cx中。
    查询指令手册,与MOV r16,imm16指令相符,其操作码为B8+ rw,rw表示目的操作数cx寄存器编号。
    在这里插入图片描述
    当前指令cx编号为1,因此操作码为B8+1=B9。
    由于在X64下,默认操作数宽度是32位,需要添加指令前缀66H,“反转”选择16位宽度的操作数。
    因此指令的机器码组成,如下所示:
汇编指令指令前缀操作码立即数机器码
mov cx, 1234h66B9123466B93412
  • mov ecx, 12345678h
    mov ecx, 12345678h表示将立即数12345678h存储到32位寄存器ecx中。
    查询指令手册,与MOV r32,imm32指令相符,其操作码为B8+ rd,rd表示目的操作数ecx寄存器编号。
    在这里插入图片描述
    当前指令ecx编号为1,因此操作码为B8+1=B9。
    由于在X64下,默认操作数宽度是32位,刚好合适,因此不需添加指令前缀66H。
    因此指令的机器码组成,如下所示:
汇编指令操作码立即数机器码
mov ecx, 12345678hB912345678B978563412
  • mov rcx, 1122334455667788h
    mov rcx, 1122334455667788h表示将立即数1122334455667788h存储到64位寄存器rcx中。
    查询指令手册,与MOV r64,imm64指令相符,其操作码为REX.W + B8+ rd,rd表示目的操作数rcx寄存器编号。
    在这里插入图片描述
    当前指令rcx编号为1,因此操作码为B8+1=B9。
    REX.W说明需要REX前缀,REX.W=1表示操作位宽为64位,因此REX=48h。
    因此指令的机器码组成,如下所示:
汇编指令REX前缀操作码立即数机器码
mov rcx, 1122334455667788h48B91122334455667788h48 B9 88 77 66 55 44 33 22 11

2.2 mov rcx,[r8]与mov [r8],rcx

  • mov rcx,[r8]
    mov rcx,[r8]表示将r8寄存器中地址指向的内存单元,存储到rcx中。
    查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
    在这里插入图片描述
    当前指令寻址方式属于《X64指令基本格式》中“第一种,无SIB字节的内存寻址”。
    在这里插入图片描述
    因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m、REX.B三者确定一种寻址方式,如下图:
    在这里插入图片描述
    第一步,在源和目的操作数中,以内存寻址操作数为坐标点,反推ModRM.mod、ModRM.r/m、REX.B。
    这里内存寻址操作数为[r8],故ModRM.mod=00,ModRM.r/m=000,REX.B=1。
    第二步,在源和目的操作数中,以寄存器操作数,反推ModRM.reg与REX.R。
    这里寄存器操作数为rcx,其寄存器编号Rrrr=0001,故REX.R=0,ModRM.reg=001。

REX.W说明需要REX前缀,REX格式为0100WRXB,W表示操作数宽度,W=1表示64位,X位默认为0,因此REX=01001001=49h。ModRM=00001000=08h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRM机器码
mov rcx,[r8]498B08498B08
  • mov [r8],rcx
    mov [r8],rcx表示将rcx寄存器内容,存储到r8寄存器中地址指向的内存单元中。
    查询指令手册,与MOV r/m64,r64指令相符,其操作码为REX.W + 89 /r,/r表示这条指令具有ModR/M字段。
    在这里插入图片描述
    当前指令寻址方式属于《X64指令基本格式》中“第一种,无SIB字节的内存寻址”。
    因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m、REX.B三者确定一种寻址方式,如下图:
    在这里插入图片描述
    第一步,在源和目的操作数中,以内存寻址操作数为坐标点,反推ModRM.mod、ModRM.r/m、REX.B。
    这里内存寻址操作数为[r8],故ModRM.mod=00,ModRM.r/m=000,REX.B=1。
    第二步,在源和目的操作数中,以寄存器操作数,反推ModRM.reg与REX.R。
    这里寄存器操作数为rcx,其寄存器编号Rrrr=0001,故REX.R=0,ModRM.reg=001。

REX.W说明需要REX前缀,REX格式为0100WRXB,W表示操作数宽度,W=1表示64位,X位默认为0,因此REX=01001001=49h。ModRM=00001000=08h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRM机器码
mov [r8],rcx498908498908

发现没有,源操作数与目的操作数,交换传输方向后,仅操作码发生变化。也就是说,寄存器与内存之间传递数据的方向,是靠操作码来分辨的,与REX前缀、ModRM无关。

2.3 mov rcx,[r8+r9*2]

mov rcx,[r8+r9*2]表示将r8寄存器中地址+r9寄存器中地址*2,指向的内存单元,存储到rcx中。
查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
在这里插入图片描述
当前指令寻址方式属于《X64指令基本格式》中“第三种,带SIB字节的内存寻址”,如下图所示:
在这里插入图片描述
此场景下REX.B与SIB.base合并,不再与ModRM.r/m合并。
因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m两者就可以确定[SIB]内存寻址方式,如下图:
在这里插入图片描述
第一步,以内存寻址操作数为坐标点,反推ModRM.mod、ModRM.r/m。
这里内存寻址操作数为[r8+r9 * 2],故ModRM.mod=00,ModRM.r/m=100。

第二步,以寄存器操作数,反推ModRM.reg与REX.R。
这里寄存器操作数为rcx,其寄存器编号Rrrr=0001,故REX.R=0,ModRM.reg=001。

第三步,SIB寻址[r8+r9 * 2],根据effective_address = scale * index + base + offset地址计算公式,得出base为r8,index为r9,scale为2,无offset。

REX.B与SIB.base拼成的Bbbb,表示基地址寄存器(r8)的编号,Bbbb=1000,故REX.B=1,SIB.base=000。
REX.X与SIB.index拼成的Xxxx,表示索引寄存器(r9)的编号,Xxxx=1001,故REX.X=1,SIB.index=001。

scale机器码编码,如下所示:

scaleEncoded value
100
201
410
811

scale为2,因此对应机器码为01。

REX格式为0100WRXB,REX.W=1表示操作数宽度为64位。
我们基于上述这些位,得出REX=0100 1011=4Bh,Opcode=8Bh,ModRM=00001100=0Ch,SIB=01001000=48h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRMSIB机器码
mov rcx,[r8+r9*2]4B8B0C484B8B0C48

2.4 mov rcx,[00001000h]

mov rcx,[00001000h]表示将00001000h地址指向的内存单元,存储到rcx中。
查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
在这里插入图片描述
当前指令寻址方式属于《X64指令基本格式》中“第三种,带SIB字节的内存寻址(mod!=11 & r/m=100)”,一定有疑问,这指令看起来,跟SIB一般形式不像,我们通过查看其机器码,发现的确属于第三种场景。
在这里插入图片描述

因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m两者确定一种内存寻址方式,如下图:
在这里插入图片描述

第一步,在源和目的操作数中,以内存寻址操作数为坐标点,反推ModRM.mod、ModRM.r/m。
这里内存寻址操作数为[00001000h],故ModRM.mod=00,ModRM.r/m=100。

第二步,在源和目的操作数中,以寄存器操作数,反推ModRM.reg与REX.R。
这里寄存器操作数为rcx,其寄存器编号Rrrr=0001,故REX.R=0,ModRM.reg=001。

第三步,我们知道SIB地址形式,通常是这样effective_address = scale * index + base + offset,但是对于当前指令mov rcx,[00001000h],如果要匹配的话,那么base和index寄存器不存在,scale为1,offset=00001000h,因此SIB=25h,如下所示:
在这里插入图片描述
REX.B与SIB.base拼成的Bbbb,表示基地址寄存器(base)的编号,Bbbb=0101,故REX.B=0,SIB.base=101。
REX.X与SIB.index拼成的Xxxx,表示索引寄存器(index)的编号,Xxxx=0100,故REX.X=0,SIB.index=100。

REX.W说明需要REX前缀,REX格式为0100WRXB,W表示操作数宽度,W=1表示64位,因此REX=01001000=48h。ModRM=00001100=0Ch。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRMSIB偏移机器码
mov rcx,[00001000h]488B0C2500001000488B0C2500100000

本例子,正是属于RIP寻址方式中,红框所示的场景。
在这里插入图片描述
至于mod=00,r/m=101的场景,留待以后再讨论。

2.5 mov rcx,[r8+10h]

mov rcx,[r8+10h]表示将r8寄存器中地址+10h,指向的内存单元,存储到rcx中。
查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
在这里插入图片描述
当前指令寻址方式属于《X64指令基本格式》中“第一种,无SIB字节的内存寻址”。
在这里插入图片描述
因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m、REX.B三者确定一种寻址方式,如下图:
在这里插入图片描述

第一步,在源和目的操作数中,以内存寻址操作数为坐标点,反推ModRM.mod、ModRM.r/m、REX.B。
这里内存寻址操作数为[r8+10h],故ModRM.mod=01,ModRM.r/m=000,REX.B=1。
第二步,在源和目的操作数中,以寄存器操作数,反推ModRM.reg与REX.R。
这里寄存器操作数为rcx,其寄存器编号Rrrr=0001,故REX.R=0,ModRM.reg=001。

REX.W说明需要REX前缀,REX格式为0100WRXB,W表示操作数宽度,W=1表示64位,X位默认为0,因此REX=01001001=49h。ModRM=01001000=48h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRM偏移机器码
mov rcx,[r8+10h]498B4810498B4810

2.6 mov rcx,[r8+r9*2+10h]

mov rcx,[r8+r9*2+10h]表示将r8寄存器中地址+r9寄存器中地址*2+10h,指向的内存单元,存储到rcx中。
查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
在这里插入图片描述
当前指令寻址方式属于《X64指令基本格式》中“第三种,带SIB字节的内存寻址”,如下图所示:
在这里插入图片描述
此场景下REX.B与SIB.base合并,不再与ModRM.r/m合并。
因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m两者就可以确定[SIB+disp8]内存寻址方式,如下图:
在这里插入图片描述

第一步,以内存寻址操作数为坐标点,反推ModRM.mod、ModRM.r/m。
这里内存寻址操作数为[r8+r9 * 2+10h],故ModRM.mod=01,ModRM.r/m=100。

第二步,以寄存器操作数,反推ModRM.reg与REX.R。
这里寄存器操作数为rcx,其寄存器编号Rrrr=0001,故REX.R=0,ModRM.reg=001。

第三步,SIB寻址[r8+r9 * 2+10h],根据effective_address = scale * index + base + offset地址计算公式,得出base为r8,index为r9,scale为2,offset为10h。

REX.B与SIB.base拼成的Bbbb,表示基地址寄存器(r8)的编号,Bbbb=1000,故REX.B=1,SIB.base=000。
REX.X与SIB.index拼成的Xxxx,表示索引寄存器(r9)的编号,Xxxx=1001,故REX.X=1,SIB.index=001。

scale机器码编码,如下所示:

scaleEncoded value
100
201
410
811

scale为2,因此对应机器码为01。

REX格式为0100WRXB,REX.W=1表示操作数宽度为64位。
我们基于上述这些位,得出REX=0100 1011=4Bh,Opcode=8Bh,ModRM=01001100=4Ch,SIB=01001000=48h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRMSIB偏移机器码
mov rcx,[r8+r9*2+10h]4B8B4C48104B8B4C4810

2.7 mov rcx,[r8+00001000h]

与mov rcx,[r8+10h]类似,不再赘述。

2.8 mov rcx,[r8+r9*2+00001000h]

与mov rcx,[r8+r9*2+10h]类似,不再赘述。

2.9 mov r9,r8与mov r8,r9

  • mov r9,r8
    mov r9,r8表示将r8寄存器内容,存储到r9中。
    查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
    在这里插入图片描述

当前指令寻址方式属于《X64指令基本格式》中“第二种,寄存器到寄存器的寻址(无内存操作数,mod=11)”。
在这里插入图片描述

因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m、REX.B三者确定一种寻址方式,如下图:
在这里插入图片描述
在这里插入图片描述

当寄存器与寄存器间传送数据时:
第一步,以源操作数为寻址方式,反推ModRM.mod、ModRM.r/m、REX.B。
这里源操作数为r8,故ModRM.mod=11,ModRM.r/m=000,REX.B=1。

第二步,以目的操作数,反推ModRM.reg与REX.R。
这里目的操作数为r9,其寄存器编号Rrrr=1001,故REX.R=1,ModRM.reg=001。

REX.W说明需要REX前缀,REX格式为0100WRXB,W表示操作数宽度,W=1表示64位,X位默认为0,因此REX=01001101=4Dh。ModRM=11001000=C8h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRM机器码
mov r9,r84D8BC84D 8B C8
  • mov r8,r9
    mov r8,r9表示将r9寄存器内容,存储到r8中。
    查询指令手册,与MOV r64,r/m64指令相符,其操作码为REX.W + 8B /r,/r表示这条指令具有ModR/M字段。
    在这里插入图片描述

当前指令寻址方式属于《X64指令基本格式》中“第二种,寄存器到寄存器的寻址(无内存操作数,mod=11)”。
在这里插入图片描述

因此,尝试推导ModR/M值。ModRM.mod、ModRM.r/m、REX.B三者确定一种寻址方式,如下图:
在这里插入图片描述在这里插入图片描述
当寄存器与寄存器间传送数据时:
第一步,以源操作数为寻址方式,反推ModRM.mod、ModRM.r/m、REX.B。
这里源操作数为r9,故ModRM.mod=11,ModRM.r/m=001,REX.B=1。

第二步,以目的操作数,反推ModRM.reg与REX.R。
这里目的操作数为r8,其寄存器编号Rrrr=1000,故REX.R=1,ModRM.reg=000。

REX.W说明需要REX前缀,REX格式为0100WRXB,W表示操作数宽度,W=1表示64位,X位默认为0,因此REX=01001101=4Dh。ModRM=11000001=C1h。
因此指令的机器码组成,如下所示:

汇编指令REX前缀操作码ModRM机器码
mov r8,r94D8BC14D 8B C1
mov r9,r8 : 4D 8B C8

mov r8,r9与mov r9,r8的机器码,仅有ModR/M不一样,其他均一致。
我们可以看出,当寄存器与寄存器之间进行数据操作时,ModR/M值决定了,寄存器写入的方向。


参考文档:

### 回答1: MIPS汇编指令在线转换机器码是一种在互联网上提供的工具,可以将MIPS汇编语言指令转换为对应的机器码。 MIPS汇编指令是一种低级语言,用于编写基于MIPS体系结构的计算机程序。它使用助记符和操作数来表示不同的指令,以便程序员更容易地理解和编写代码。然而,计算机硬件只能理解机器码,即由二进制数字表示的指令。 在线转换工具通过解析输入的MIPS汇编指令,将其转换机器码,以便计算机能够执行相应的操作。转换的过程涉及到识别和解析指令中的助记符和操作数,并根据MIPS指令集架构的规则将其转化为对应的机器码表示。 通过在线转换机器码的工具,程序员可以验证他们编写的汇编代码是否正确,并且可以理解每条指令在计算机内部的表示形式。此外,这个工具还可以帮助初学者学习和理解MIPS汇编语言的基本知识,并且能够快速转换并输出机器码。 总之,MIPS汇编指令在线转换机器码是一种方便的工具,可以将MIPS汇编指令转换为计算机能够理解和执行的机器码。它有助于程序员验证代码的正确性,并促进对MIPS汇编语言的学习和理解。 ### 回答2: MIPS(Microprocessor without Interlocked Pipeline Stages)汇编语言是一种基于RISC(Reduced Instruction Set Computer)架构的指令集,常用于嵌入式系统和计算机体系结构的学习中。MIPS汇编指令集较为简洁,有助于理解计算机底层的工作原理。 将MIPS汇编指令转换机器码是让计算机能够理解和执行指令的过程。通常,在进行这种转换时,需要参考MIPS指令集手册来确定每个指令的操作码(Opcode)、寄存器操作数(Register Operand)和立即数(Immediate Operand),以及一些其他可能的参数。 转换MIPS汇编指令机器码的过程可以分为以下几个步骤: 1. 根据指令的类型(例如,存储、加载、运算等),确定操作码。每个操作码对应一个特定的指令。 2. 根据指令中包含的寄存器操作数和立即数,确定相应的二进制表示。 3. 将操作码和操作数转换为二进制,并按照特定的顺序排列这些位。 4. 组合确定指令格式的各个部分,生成完整的二进制机器码。 以MIPS的ADD(加法)指令为例,其汇编语言表示为"ADD r1, r2, r3",其中r1、r2和r3是寄存器。根据MIPS指令集手册,ADD指令的操作码是"000000",而r1、r2和r3分别对应于不同的寄存器编号,例如,r1为"00001"、r2为"00010"和r3为"00011"。因此,将ADD指令转换机器码时,操作码为"000000",寄存器操作数为"00001"、"00010"和"00011",其二进制表示为"000000 00001 00010 00011"。 如此类推,可以通过查找MIPS指令集手册中每个指令的相关信息,并遵循规定的转换流程,将所有MIPS汇编指令转换为对应的机器码。这样,计算机就能够根据转换后的机器码执行相应的指令,完成特定的任务。 ### 回答3: MIPS(Microprocessor without Interlocked Pipelined Stages)是一种常用的RISC(Reduced Instruction Set Computer)架构的计算机处理器。MIPS汇编语言是一种常用的底层编程语言,主要用于编写MIPS指令集架构的程序。 要将MIPS汇编指令转换机器码,可以使用在线工具或软件来实现。这些工具通常提供一个用户界面,让用户输入MIPS指令,并自动将其转换为相应的机器码。 在在线转换机器码的过程中,用户需要提供MIPS指令的正确写法和语法。例如,用户可以输入“add $t0, $t1, $t2”来表示将$t1和$t2寄存器中的值相加,并将结果存储在$t0寄存器中。转换工具会根据MIPS指令的操作码、寄存器编号等信息来生成相应的机器码。例如,对于上述的add指令,其对应的机器码可能是“000000 01001 01010 01000 00000 100000”。 在线转换机器码的工具通常支持多种类型的MIPS指令,包括算术操作指令、逻辑操作指令、数据传输指令等。用户可以根据自己的程序需求,在工具中选择相应的指令类型,并提供相应的操作数和操作码。 需要注意的是,在在线转换机器码之前,用户应该确保输入的MIPS指令是正确的,并符合MIPS指令集的规范。否则,转换过程可能会出现错误或生成无效的机器码。 总之,通过使用在线工具或软件,可以方便地将MIPS汇编指令转换机器码。这样的工具为开发人员提供了一种快速和准确地生成MIPS指令对应机器码的方法,有助于在MIPS架构的计算机处理器上编写和运行程序。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值