x86汇编语言知识点

逆向笔记 · 03-21 · 118 人浏览

一、条件跳转指令

特定标志值的跳转

jz 为零跳转 zf=1

jnz 非零跳转 zf=0

jc 有进位则跳转 cf=1

jnc 无进位则跳转 cf=0

jo 溢出则跳转 of=1

jno 无溢出则跳转 of=0

js 如果符号位为1则跳转 sf=1

jns 如果符号位为零则跳转 sf=0

jp 如果奇偶标志位为1(奇偶性为偶)则跳转 pf=1

jnp 如果奇偶标志位为0(奇偶性为奇)则跳转 pf=0

基于相等性的跳转

je 如果相等(leftop=rightop)则跳转

jne 如果不相等(leftop!=rightop)则跳转

jcxz 如果cx=0则跳转

jecxz 如果ecx=0则跳转

jrcxz 如果rcx=0则跳转

基于无符号数比较的跳转

ja 如果多于则跳转(若leftop>rightop)

jnbe 如果不是少于或等于则跳转(与ja相同)

jae 如果多于或等于则跳转(若leftop>=rightop)

jnb 如果不少于则跳转(与jae相同)

jb 如果少于则跳转(若leftop

jnae 如果不是多余或等于则跳转(与jb相同)

jbe 如果少于或等于则跳转(若left

jna 如果不多于则跳转(与jbe相同)

基于有符号数比较的跳转

jg 如果大于则跳转 (若leftop>rightop)

jnle 如果不是小于或等于则跳转(与jg相同)

jge 如果大于或等于则跳转(若leftop>=rightop)

jnl 如果不小于则跳转(与jge相同)

jl 如果小于则跳转(若leftop

jnge 如果不是大于或等于则跳转(与jl相同)

jle 如果小于或等于则跳转(若leftop

vs中调试的各种标志位详解

溢出标志OF(Over flow flag) OV(1) NV(0)

方向标志DF(Direction flag) DN(1) UP(0)

中断标志IF(Interrupt flag) EI(1) DI(0)

符号标志SF(Sign flag) NG(1) PL(0)

零标志ZF(Zero flag) ZR(1) NZ(0)

辅助标志AF(Auxiliary carry flag) AC(1) NA(0)

奇偶标志PF(Parity flag) PE(1) PO(0)

进位标志CF(Carry flag) CY(1) NC(0)

二、__readfsqword()

__readfsqword是汇编指令,用于读取 FS 段寄存器中存储的 64 位整数。
__readfsqword(0x28u)赋值给变量v7则表示将 FS 段寄存器中偏移为0x28的地址处存储的 64 位整数值赋值给变量v7。

三、常见指令

1.lea

Load effective address(EA)——取有效地址,即偏移地址
lea指令用于把源操作数的地址偏移量传送目的操作数。
源操作数一定要是一个存贮器操作数,而目的操作数可以是任何的16位的通用寄存器,包括指针寄存器/变址寄存器。

2.xor

XOR指令在两个操作数的对应位之间进行(按位)逻辑异或(XOR)操作,并将结果存在目标操作数中

XOR destination,source

XOR指令操作数组合和大小于AND指令以及OR指令相同。两个操作数的每一对对应位都应用如下操作原则:如果两个位值相同(同为0或同为1),则结果位等于0;否则结果位等于1。下标描述的是布尔运算xy:

### y## x## x⊕y
000
011
101
110

四、8086汇编语言基础知识总结

一、寄存器

1、4个数据寄存器(16位):

AX(AH、AL)

BX(BH、BL):常用作基数寄存器(即数据段的偏移地址寄存器)

CX(CH、CL)

DX(DH、DL)

2、指针寄存器

BP:基数指针寄存器,用作堆栈段的偏移地址寄存器

SP:堆栈指针寄存器,用于堆栈段的偏移地址寄存器

3、变址寄存器

SI:源变址寄存器,与BX功能相近,但更常用于变址寻址

DI:目的变址寄存器,与BX功能相近,但更常用于变址寻址

4、4个段寄存器

  • CS:代码段寄存器,存放代码段的段地址
  • DS:数据段寄存器,存放数据段的段地址
  • SS:堆栈段寄存器,存放堆栈段的段地址
  • ES:附加数据段寄存器,当DS被占用后,可以另外使用ES来充当另外一个数据段的寄存器

5、其他

  • IP:指令指针寄存器(用作代码段的偏移地址寄存器)

6、状态标志寄存器

16位,有9个标志,见下文标志寄存器部分。

7、附:代码段、数据段、堆栈段

CS:IP(即物理地址为CSx16+IP)指向的指令即为当前正要执行的指令。

DS:BP(或DS:BX)指向的数据段,为当前可以读取的数据段

SS:SP指向当前正在读取的堆栈段地址。SS:SP指向的是栈顶元素

8、附:未显式给出段寄存器时的默认段寄存器

含有BX、DI、SI的寻址,默认段寄存器为DS

含有BP的寻址(同时含有BP和BX/SI/SI也属于这种情况),默认段寄存器位SS

二、8086执行指令的过程

  1. 从CS:IP指向的内存单元读取指令,读到指令缓冲器中。
  2. IP=IP+指令的长度,指向下一条指令.
  3. 执行指令,转到步骤1。

三、8086PC中内存的存储方式

1、8086对字的存储方式

8086的一个内存单元为8位,1字节。对于一个字,8086采用小端模式(little-endian)在内存中存储,即一个字的高字节放到高地址,低字节放到低地址

2、8086的物理地址

8086CPU有20位地址总线,16位数据总线。

8086的20位物理地址通过16位的段地址和16位的偏移地址合成,公式如下:

物理地址段地址偏移地址物理地址=段地址×16+偏移地址

四、基本汇编指令

1、数据传送指令

(1)MOV——移动指令

MOV dest,src ;(dest)=(src)

MOV指令用来完成数据移动操作

MOV指令可以完成的9种操作:

  • 通用寄存器-->通用寄存器
  • 立即数-->通用寄存器
  • 立即数-->内存
  • 内存-->通用寄存器:MOV AX,DS:[BX]
  • 通用寄存器-->内存
  • 段寄存器(CS/IP除外)-->内存
  • 内存-->段寄存器(CS/IP除外)
  • 段寄存器(CS/IP除外)-->通用寄存器
  • 通用寄存器-->段寄存器(CS/IP除外)

MOV指令不能修改CS/IP的内容

不能直接把立即数放到段寄存器中

(2)PUSH、POP——入栈、出栈指令

入栈和出栈操作均只能以字为单位进行。

栈的格式:

  • 栈顶:低地址
  • 栈底:高地址

PUSH AX操作的含义:

  • SP=SP-2,栈顶指针空出一个字单位
  • 将AX的内容放到SS:SP指向的单元(一个字)中,SS:SP重新指向栈顶

POP AX操作的含义:

  • 将SS:SP指向的单元(一个字)内容送到AX中
  • SP=SP+2,栈顶指针向下移动一个字单位

PUSH、POP支持的操作:

  • PUSH/POP 通用寄存器
  • PUSH/POP 段寄存器
  • PUSH/POP 内存单元

(3)PUSHF、POPF——标志寄存器入栈、出栈指令

PUSHF——将标志寄存器的值压入栈中

POPF——从栈中弹出数据,送到标志寄存器中

2、算术运算指令

(1)ADD——加指令

ADD dest,src

加指令把右边的数加到左边的数中

其含义为(dest)=(dest)+(src)

可以完成的操作

  • ADD 通用寄存器,数据
  • ADD 通用寄存器,通用寄存器
  • ADD 通用寄存器,内存
  • ADD 内存,通用寄存器
  • ADD指令不能对段寄存器操作

(2)ADC——带进位加法指令

ADC dest,src

ADC指令会在执行加法时将CF位的进位值加上

其含义为:(dest)=(dest)+(src)+CF

(3)INC指令——自加1指令

INC BX,即将BX的内容自加1

(4)SUB——减指令

SUB dest,src ;(dest)=(dest)-(src)

减指令从左边的数中减去右边的数

可以完成的操作

  • SUB 通用寄存器,数据
  • SUB 通用寄存器,通用寄存器
  • SUB 通用寄存器,内存
  • SUB 内存,通用寄存器

SUB指令不能对段寄存器操作

(5)SBB——带借位减指令

SBB dest,src

SBB指令会在执行减法时将CF位的借位值减去

其含义为:(dest)=(dest)-(src)-CF

(6)DEC———自减1指令

DEC BX,即将BX的内容自减1

(7)DIV——除法指令

DIV REG/内存单元

被除数/除数=商

除数:可以为8位或者16位,放在寄存器或者内存单元中,在指令的操作数中显式给出。

被除数:根据除数的位数动态调整:

  • 如果除数为8位,则被除数为16位,需提前放在AX中,不用在指令中给出
  • 如果除数为16位,则被除数为32位,需提前放在DX(高16位)、AX(低16位)中,不需要在指令中给出

商:

  • 如果除数为8位,则商将放到AL中,余数将放到AH中
  • 如果除数为16位,则商将放到AX中,余数将放到DX中

(8)MUL——乘法指令

MUL REG/内存单元

两个数相乘,要么都是8位,要么都是16位。

如果是8位

  • 一个乘数需要提前放到AL中,无需在指令中给出
  • 另一个乘数可以放到8位寄存器或者内存单元中,需在指令中给出
  • 结果默认放到AX中

如果是16位

  • 一个乘数需要提前放到AX中,无需再指令中给出
  • 另一个乘数可以放到16位寄存器或者内存单元中,需在指令中给出
  • 结果默认高位放到DX中,低位放到AX中

(9)CMP——比较指令

CMP 对象1,对象2

  • 执行对象对象对象1−对象2的运算,但不保留运算结果,只是根据运算结果对相应的标志寄存器进行置位

3、逻辑指令

(1)AND、OR、NOT、XOR、TEST——与、或、非、异或等指令

  • AND AL,BL:将BL与AL的值进行按位与运算,结果存放到AL中
  • OR AL,BL:将BL与AL的值进行按位或运算,结果存放到BL中
  • XOR AL,BL:将BL与AL的值进行按位异或运算,结果存放到BL中
  • NOT AL:对AL各位取反,不改变标志寄存器的值
  • TEST AL,BL:将BL与AL的值进行按位与运算,不保存运算结果,只改变标志寄存器。
  • 两个操作数不能同时为内存单元,不能为段寄存器
  • 除了NOT,其他指令都会修改标志寄存器

(2)SHL、SHR——逻辑移位指令

SHL 寄存器/内存单元,1的功能:

  • 对寄存器/内存单元的数据进行向左移位
  • 最高位移出去的一位放到CF中
  • 最低位缺失的位用0补充

SHR 寄存器/内存单元,1的功能:

  • 对寄存器/内存单元的数据进行向右移位
  • 最低位移出去的一位放到CF中
  • 最高位缺失的位用0补充
  • 如果移动位数大于1,则需要把移动位数放到CL寄存器中

4、转移指令

(1)JMP——无条件跳转指令

JMP 2AE3:3 ;CS=2AE3H, IP=0003H
JMP AX ;IP=AX
  • JMP指令用来修改CS和IP寄存器的值,即实现指令执行位置的跳转功能

JMP指令的几种形式:

段内短转移

JMP SHORT 标号:功能为(IP)=(IP)+转移距离(标号距离当前指令的距离,8位,因为是段内短转移)

段内近转移

JMP NEAR PTR 标号:功能为(IP)=(IP)+转移距离(标号距离当前指令的距离,16位,因为是段内短转移)

段间转移(远转移)

JMP FAR PTR 标号:功能为(CS)=所在段的段地址;(IP)=标号在段中的偏移地址

地址在寄存器中的转移

JMP 16位寄存器:功能为(IP)=(16位寄存器)

地址在内存的段内转移

JMP WORD PTR 内存单元地址(用[]的方式表示):功能为(IP)=该内存单元地址处存放的一个字

地址在内存的段间转移

JMP DWORD PTR 内存单元地址:功能为(CS)=(内存单元地址+2)(即内存单元地址高地址处存放的字);(IP)=(内存单元地址)(即内存单元地址低地址处存放的字)

(2)有条件跳转指令合集

1)JCXZ

形式:JCXZ 标号

功能:如果(CX)=0,则跳转到标号处(即(IP)=(IP)+转移距离(8位));否则不跳转。

所有的有条件跳转指令都只能进行短转移

以下的有条件跳转指令根据标志位的情况置位(常与CMP指令配合,根据CMP指令无符号数的运算结果置位)

2)JE

形式:JE 标号

功能:当标志位ZF=1时,转移到标号处

与CMP配合:当A=B时,跳转到标号处

CMP A B
JE 标号

3)JNE

形式:JNE 标号

功能:当标志位ZF=0时,转移到标号处

与CMP配合:当A!=B时,跳转到标号处

CMP A B
JNE 标号

4)JB

形式:JB 标号(B代表below)

功能:当标志位CF=1时,转移到标号处

与CMP配合:当A<B时,跳转到标号处(如果A<B,则A-B有借位,于是CF=1)

CMP A B
JB 标号

5)JNB

形式:JNB 标号(NB代表not below)

功能:当标志位CF=0时,转移到标号处

与CMP配合:当A>=B时,跳转到标号处(如果A>=B,则A-B无借位,于是CF=0)

CMP A B
JNB 标号

6)JA

形式:JA 标号(A代表above)

功能:当标志位CF=0且ZF=0时,转移到标号处

与CMP配合:当A>B时,跳转到标号处(如果A>B,则A-B无借位,于是CF=0;若A!=B,则ZF=0)

CMP A B
JA 标号

7)JNA

形式:JNA 标号(NA代表not above)

功能:当标志位CF=1或ZF=1时,转移到标号处

与CMP配合:当A<=B时,跳转到标号处(如果A<B,则A-B有借位,于是CF=1;若A=B,则CF=0且ZF=1。故合起来就是CF=1或ZF=1)

CMP A B
JNA 标号

(4)LOOP——循环指令

LOOP S的作用

  • 1.(CX)=(CX)-1
  • 2.判断(CX)是否为0,若不为零,在跳转到标号S处((IP)=(IP)+转移距离(8位)),继续执行程序,否则退出循环
所有的循环指令都只能进行短转移

(5)RET、RETF——返回指令

RET——段内转移

功能:将栈顶数据弹出,然后以栈顶数据作为偏移地址进行段内跳转

详细操作:

  • (IP)=((SS)*16+(SP))——利用栈顶元素修改(IP),段内跳转
  • (SP)=(SP)+2——弹出栈顶元素

RETF——段间转移

功能:将栈顶的两个元素先后弹出,弹出的第一个元素作为跳转的偏移地址,弹出的第二个元素作为跳转的段地址

详细操作:

  • (IP)=((SS)*16+(SP))——利用栈顶元素修改IP,获得偏移地址
  • (SP)=(SP)+2——弹出栈顶元素
  • (CS)=((SS)*16+(SP))——利用新栈顶元素修改CS,获得段地址
  • (SP)=(SP)+2——再次弹出栈顶元素

(6)CALL——调用指令

CALL 标号

功能:将当前的IP值压入栈中,然后转到标号处执行指令

详细操作:

  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(IP)——IP压入栈中
  • (IP)=(IP)+偏移地址(16位)——跳转到标号处

CALL FAR PTR 标号

功能:先将当前的段地址CS压入栈中,然后将当前的偏移地址IP压入到栈中。最后把CS和IP修改为标号的段地址和偏移地址,实现段间转移

详细操作:

  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(CS)——CS压入栈中
  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(IP)——IP压入栈中
  • (CS)=标号所在段的段地址
  • (IP)=标号在段中的偏移地址

CALL 寄存器

功能:将当前的IP值压入栈中,然后转到寄存器指出的偏移地址处执行指令

详细操作:

  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(IP)——IP压入栈中
  • (IP)=(寄存器)——跳转到寄存器偏移地址处

CALL WORD PTR 内存单元地址

功能:将当前的IP值压入栈中,然后转到内存单元指出的偏移地址处执行指令

详细操作:

  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(IP)——IP压入栈中
  • (IP)=(内存单元)——跳转到内存单元偏移地址处

CALL DWORD PTR 内存单元地址

功能:先将当前的段地址CS压入栈中,然后将当前的偏移地址IP压入到栈中。最后把CS改为内存单元的高字,IP改为内存单元的低字,实现段间转移

详细操作:

  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(CS)——CS压入栈中
  • (SP)=(SP)-2——栈顶空出一个元素
  • ((SS)*16+(SP))=(IP)——IP压入栈中
  • (CS)=(内存单元的高字)
  • (IP)=(内存单元的低字)

5、串操作指令

(1)MOVSB——字节串传送指令

功能:将DS:SI指向的内存单元的一个字节的数据送入ES:DI指向的内存单元中。然后如果DF=0,则SI自增1,DI自增1;如果DF=1,则SI自减1,DI自减1

详细操作:

  • ((ES)16+(DI))=((DS)16+(SI))(字节)
  • 如果DF=0,则(SI)=(SI)+1,(DI)=(DI)+1
  • 如果DF=1,则(SI)=(SI)-1,(DI)=(DI)-1

(2)MOVSW——字串传送指令

功能:将DS:SI指向的内存单元的一个字的数据送入ES:DI指向的内存单元中。然后如果DF=0,则SI自增2,DI自增2;如果DF=1,则SI自减2,DI自减2

详细操作:

  • ((ES)16+(DI))=((DS)16+(SI))(字)
  • 如果DF=0,则(SI)=(SI)+2,(DI)=(DI)+2
  • 如果DF=1,则(SI)=(SI)-2,(DI)=(DI)-2

(3)REP——重复指令(与串操作指令配合使用)

REP指令要与MOVSB或者MOVSW配合使用,如下:

REP MOVSB/MOVSW

  • 功能:重复执行MOVSB/MOVSW指令,每执行一次,CX减1。直到减到0,停止重复。
  • 以上指令等价于:
S:  MOVSB/MOVSW
    LOOP S
  • REP实现了对于CX个连续单位(字节/字)的串操作,需要提前对DF位和CX进行合理设置
  • DF提供方向信息,CX提供长度信息

(4)CLD/STD——DF方向标志位置位指令

CLD——将DF清0

STD——将DF置1

6、中断处理指令

(1)IRET——中断返回指令

IRET的功能为,先从栈中弹出一个字到IP中,然后再从栈中弹出一个字到CS中,最后从栈中弹出一个字到标志寄存器中。

IRET相当于

POP IP
POP CS
POPF

一般将IRET放到中断程序的最后,表示退出中断程序,返回到原来程序中继续执行。

(2)INT——中断调用指令

INT N

表示引发N号中断,N为中断类型码。整个中断过程如下:

  • 取中断类型码N
  • 标志寄存器入栈,设置IF=0,TF=0
  • CS,IP先后入栈
  • (IP)=(N 4),(CS)=(N 4+2),即跳转到中断向量表指出的中断程序处执行。

在AH寄存器中需提前存放中断调用的子程序号

INT与IRET配合,类似于CALL与RET配合

(3)STI/SLI——IF位置位指令

STI——设置IF=1

CLI——设置IF=0

(4)INTO——4号中断调用指令

如果OF=1,则INTO相当于INT 4,调用溢出中断。如果OF=0,则什么都不做。

7、端口(I/O)操作指令

IN指令为从端口读入数据指令

OUT指令为从寄存器输出到端口的指令

端口号的范围只能是0~65535

当端口号为0~255时

  • IN AL,20H表示从20H端口读入一个字节到AL中
  • OUT 20H,AL表示把AL的值写入到20H端口

当端口号为256~65535时

  • 需要先把端口号放到DX中,然后
  • IN AL,DX表示从DX端口读入一个字节到AL中
  • OUT DX,AL表示把AL的值写入到DX端口

IN/OUT指令只能使用AX或AL来存放读出或写入的数据,8位数据用AL,16位数据用AX

五、中断及中断过程

1、中断向量表

中断向量表中存放着每个中断类型码对应的中断程序入口地址。一个入口地址(中断描述符)包含4字节,前两字节为偏移地址,将被放到IP中;后两字节为段地址,将被放到CS中。将所有的入口地址以中断类型码为顺序排列为一张表,即为中断向量表。

中断向量表常存放在内存的开头,从0000:0000开始。

2、中断的过程(INTR请求)

  • 外设通过总线向CPU发送中断请求,CPU接受到INTR信号,且如果IF=1,则响应中断
  • 通过中断响应信号INTA(非),给出两个负脉冲。第一个负脉冲通知外设已受理中断。在第二个负脉冲后,外设通过低8位数据总线,发出中断类型码。CPU收到后,对其进行暂存
  • 保护现场:将标志寄存器的值入栈
  • 避免冲突:将现在标志寄存器的TF、IF设为0
  • 保护现场:将CS、IP先后入栈
  • 根据中断类型码N,在中断向量表中读取对应的中断程序入口地址,并存放到IP和CS中。(IP)=(N 4),(CS)=(N 4+2)

3、外中断

(1)可屏蔽中断

由外设通过端口发出的中断类型之一,当IF=0时,可以屏蔽该中断。

其中断过程与内中断基本一致。

(2)不可屏蔽中断

CPU不可屏蔽、必须响应的外中断,中断类型码固定为2,无需取中断类型码。

六、标志寄存器

8086的标志寄存器有16位,其中有9位是有用的,称为9个标志。

1、ZF标志位——zero flag零标志位

  • 相关指令执行后,如果结果位0,则ZF=1;否则ZF=0

2、PF标志位——parity flag奇偶标志位

  • 相关指令执行后,如果结果中1的个数为偶数,则PF=1;如果是奇数,则PF=0

3、SF标志位——signal flag符号标志位

  • 相关指令执行后,如果结果为负数(即结果的最高位为1),则SP=1;如果结果为正数(即结果的最高位为0),则SP=0
  • 在计算机中,不对有符号数和无符号数进行区分,计算机统一当作无符号数进行运算(不管符号位),结果根据需求人为地解读成有符号数或者无符号数
  • 如果要把结果解读成无符号数,则SF位是没有用的;如果要把结果解读成有符号数,则SF位有用。SF一直等于结果的最高位。

4、CF标志位——carry flag进位标志位

  • 在相关指令执行后,在进行无符号运算时,如果加法有进位、或者减法有借位,则CF=1;否则CF=0
  • 注意:这里的加减运算完全按照无符号数规则进行运算,不管符号位,算出多少就是多少

5、OF标志位——overflow flag溢出标志位

在相关指令执行后,在进行有符号运算时,如果有溢出(8位有符号运算超出了-128~127的范围,16位有符号数运算超出了-32768~32767的范围。或者两个正数加出了负数,两个负数加出了正数),则OF=1;否则OF=0

判断溢出的方法(方法1):

  • (方法1)对需要运算的两个操作数当作无符号数进行简单加减运算,如果两个操作数的最高位均为1,且运算结果最高位为0;或者两个操作数的最高位均为0,且运算结果最高位为1,则发生了溢出,OF=1;否则OF=0
  • (方法2)如果两个待运算的操作数的最高位为一0一1(一正一负),则需要用此方法。首先将待运算的两个操作数当作补码,还原为两个有符号原码(如果是正数,则补码就是原码;如果是负数,最高符号位不变,其他位取反,然后加1),然后将两个有符号原码化为十进制,进行带符号的运算,查看运算结果。如果运算结果不在[−128,127](8位运算)或[−32768,32767](16位运算)范围内,则发生了溢出,OF=1,否则OF=0

6、DF标志位——direction flag方向标志位

在串操作中,指示串操作方向的标志位。

如果DF=0,则SI、DI在串操作后自增

如果DF=1,则SI、DI在串操作后自减

7、TF标志位——Tracking flag跟踪标志位

用于单步跟踪调试的标志位

如果TF=1,则CPU在每执行完一条指令后就触发单步中断

如果TF=0,则不会单步中断。

8086要求在进入中断处理程序之前,把TF设为0,避免反复调用导致死循环。

8、IF标志位——Interruption enabled flag中断允许标志位

当IF=0时,不响应可屏蔽中断

当IF=1时,响应可屏蔽中断

六、寻址方式

摘自王爽汇编语言

Pasted image 20231211135733.png

五、常见指令的OPcode

每个指令都有一个或者多个编码.
如下常见的

指令OpCode说明
ret0xC3返回
short jump0xEB短跳转 8位
far jump0xEA长跳转,可以在4GB空间任意跳转 32位
jmp0xE9无条件跳转
nop0x90空指令
je/jz0x74判断是否相等
jne/jnz0x75判断是否不等
nop0x90空指令
call0xE8调用指令
汇编语言 x86
Theme Jasmine by Kent Liao