数字在计算中的表示
计算机中所有数都是以补码形式存储的,正数的原码、反码、补码相同,负数的反码等于原码取反,补码等于反码加1
无符号数: 0000 0001 表示 1 1000 1101 表示 141
有符号数: 第一位用于表示符号位 0 正数 1负数
正数与无符号数相同但是要除掉符号位 0000 0001 表示 1
负数的计算方式为 除符号位减1取反 1010 0011 减1 1010 0010 取反 1101 1101 表示 -93
二进制运算
与运算: 汇编 and c语言 &
或运算 汇编 or c语言 |
异或运算 汇编 xor c语言 ^
非运算 汇编 not c语言 ~
左移 汇编 shl c语言 << 各二进制位全部左移,高位丢弃,低位补0
右移 汇编 shr或者sar c语言 >> 各二进制位全部右移,低位丢弃,高位补0或者补符号位
shr 表示高位用0补齐 对应c语言 unsigned int a = 10; a >> 2;
sar 表示高位用符号位补齐(保证除2之后符号不变) 对应c语言 int a = 10; a >> 2;
位运算实现加减乘除
4+5
首先进行异或运算 利用与运算判断是否有进位的情况不为0表示有进位 将与的结果和上次的结果异或 重复这个过程
0000 0100 0000 0100 0000 0001 0000 0001
xor 0000 0101 and 0000 0101 xor 0000 1000 and 0000 1000
0000 0101 0000 0100 0000 1001 0000 0000
为0表示没有进位得出结果 0000 1001 9
4-5 = 4+(-5) 注意使用补码
乘法的本质就是加法
除法 x/y = x能减去多少个y
寄存器
8个通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
1个标志寄存器:EFLAGS
6个段寄存器:CS、DS、ES、FS、GS、SS
5个控制寄存器:CR0、CR1、CR2、CR3、CR4
8个调试寄存器:DR0、DR1、DR2、DR3、DR4、DR5、DR6、DR7
4个系统地址寄存器:GDTR、IDTR、LDTR、TR
其他寄存器:EIP、TSC等。
32位 | 16位 | 8位 |
EAX | AX | AH(高8位)、AL(低8位) |
EBX | BX | BH、BL |
ECX | CX | CH、CL |
EDX | DX | DH、DL |
ESI | SI |
|
EDI | DI |
|
ESP | SP |
|
EBP | BP |
|
EAX:累加器(Accumulator), 它的低16位即是AX,而AX又可分为高8位AH和低8位AL。EAX是很多加法乘法的缺省寄存器,存放函数的返回值,用累加器进行的操作可能需要更少时间,在80386及其以上的微处理器中可以用来存放存储单元的偏移地址。AX寄存器是算术运算的主要寄存器。
EBX:基地址寄存器(Base Register), 它的低16位即是BX,而BX又可分为高8位BH和低8位BL。主要用于在内存寻址时存放基地址。
ECX:计数寄存器(Count Register),它的低16位即是CX,而CX又可分为高8位CH和低8位CL。在循环和字符串操作时,要用它来控制循环次数;在位操作 中,当移多位时,要用CL来指明移位的位数;是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX:数据寄存器(Data Register),它的低16位即是DX,而DX又可分为高8位DH和低8位DL。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址;且总是被用来放整数除法产生的余数。
ESI/EDI:分别叫做源/目标索引寄存器(Source/Destination Index Register),它们的低16位分别是SI、DI。它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串。此外,它们又作为通用寄存器可以进行任意的常规的操作,如加减移位或普通的内存间接寻址。
EBP/BSP:分别是基址针寄存器(Base Pointer Register)/堆栈指针寄存器(Stack Pointer Register),低16位是BP、SP,其内存分别放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶/底部。主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。并且规定:BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。在32位平台上,ESP每次减少4字节。EBP最经常被用作高级语言函数调用的"框架指针"(frame pointer),EBP 构成了函数的一个框架,在C++反汇编中EBP通常是局部变量、传进来的参数。这里要注意在intel系统中栈是向下生长的(栈越扩大其值越小,堆恰好相反)。在通常情况下ESP是可变的,随着栈的生长而逐渐变小,而ESB寄存器是固定的,只有当函数的调用后,发生入栈操作而改变,在函数执行结束之后需要还原。
标志寄存器
OF:溢出标志。OF=1表示两个有符号数的运算结果超出了可以表示的范围,结果是错误的;OF=0表示没有溢出,结果正确。进行无符号数运算时也会产生新的OF标志(CPU不知道处理对象是否为有符号数),此时程序员可以不关心OF标志。
DF:方向标志。DF=0时,每次执行字符串指令后,源或目的地址指针用加法自动地修改地址;DF=1时用减法修改地址。它用来控制地址的方向变化。
IF:中断允许标志。IF=1表示允许处理器响应可屏蔽中断请求信号,成为开中断,IF=0表示不允许处理器响应可屏蔽中断请求信号,称为关中断。
SF:符号标志。SF=1表示运算结果的最高位为1。对于有符号数,有溢出标志OF=0时,SF=1表示运算结果为负,SF=0表示运算结果非负(正或零)。OF=1时,由于结果是错误的,所以符号位也和正确值相反。例如,两个负数相加产生溢出,此时SF=0。对于无符号数运算,SF无意义,但是可以看出结果的大小规模。
ZF:零标志。ZF=1表示运算结果为零,减法运算为零意味着两个参加运算的数大小相等;ZF=0,表示运算结果非零。
AF:辅助进位标志。它是另个BCD数运算时第三位数上的进位,供运算会调整结果用,对其他数的运算没有意义。
PF:奇偶标志。PF=1表示运算结果的低八位中有偶数个1;PF=0表示奇数个1,它可以用来进行奇偶校验。
CF:进位/借位标志。CF=1表示两个无符号数的加法有进位,或者是减法运算有借位,需要对它们的高位进行处理;CF=0表示没有产生进位或借位。同样,进行有符号数运算时也会产生新的CF标志,此时程序员可以不关心CF标志。
内存
规定访问内存的宽度
mov byte ptr ds:[0x40000], 1
mov word ptr ds:[0x40000], ax
mov dword ptr ds:[0x40000], eax
访问内存的5中形式
mov eax, 0x40000 直接立即数访问
mov eax, dword ptr ds:[ecx] 使用寄存器(8个寄存器中的任意一个)
mov eax, dword ptr ds:[ecx + 4] [寄存器 + 立即数]
mov edx, dword ptr ds:[eax + ecx * 4] [寄存器 + 寄存器 * { 1, 2, 4, 8}]
mov edx, dword ptr ds:[eax + ecx * 4 + 4] [寄存器 + 寄存器 * { 1, 2, 4, 8} + 立即数]
汇编指令
MOV
功能 : 把源操作数送给目的操作数
语法 : MOV 目的操作数 ,源操作数
格式 : MOV r1,r2 或 MOV r,m 或 MOV m,r 或 MOV r,data
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
符号扩展的意思是,当用跟多的内存存储某一个有符号数时,由于符号位位于该数的第一位,扩展之后,符号位仍然需要位于第一位,所以,当扩展一个负数的时候需要将扩展的高位全赋为1.对于正数而言,符号扩展和零扩展是一样的,因为符号位就是0.
XCHG
功能 : 交换两个操作数的数据
语法 : XCHG
格式 : XCHG r1,r2 或 XCHG m,r 或 XCHG r,m
PUSH,POP
功能 : 把操作数压入或取出堆栈
语法 : PUSH 操作数 POP 操作数
格式 : PUSH r 或 PUSH M 或 PUSH data POP r 或 POP m
PUSHF,POPF,PUSHA,POPA // PUSHFD POPFD PUSHAD POPAD
功能 : 堆栈指令群
pushf 的功能是将标志寄存器的值压栈,而 popf 是从栈中探出数据,输入标志寄存器
PUSHA/PUSHAD - 压入所有通用寄存器
格式 : PUSHF POPF PUSHA POPA
LEA,LDS,LES
功能 : 取地址至寄存器
语法 : LEA r,m LDS r,mLES r,m
XLAT(XLATB)
功能 : 查表指令
语法 : XLAT XLAT m
ADD,ADC
功能 : 加法指令
语法 : ADD OP1,OP2 ADC OP1,OP2
格式 : ADD r1,r2 ADDr,m ADD m,r ADD r,data
影响标志 : C,P,A,Z,S,O
SUB,SBB
功能 :减法指令
语法 : SUB OP1,OP2 SBB OP1,OP2
格式 : SUB r1,r2 SUBr,m SUB m,r SUB r,data SUB m,data
影响标志 : C,P,A,Z,S,O
INC,DEC
功能 : 把 OP 的值加一或减一
语法 : INC OP DEC OP
格式 : INC r/m DEC r/m
影响标志 : P,A,Z,S,O
NEG
功能 : 将 OP 的符号反相 (取二进制补码 )
语法 : NEG OP
格式 : NEG r/m
影响标志 : C,P,A,Z,S,O
MUL,IMUL
功能 : 乘法指令
语法 : MUL OP IMUL OP
格式 : MUL r/m IMUL r/m
影响标志 : C,P,A,Z,S,O( 仅 IMUL 会影响 S 标志 )
DIV,IDIV
功能 :除法指令
语法 : DIV OP IDIV OP
格式 : DIV r/m IDIV r/m
执行的操作:
字节操作:16位被除数在AX,8位除数为源操作数,结果的8位商在AL中,8位余数在AH中。表示为
(AL)<-(AX)/(SRC) 的商
(AH) <-(AX)/(SRC) 的余数
字操作:32位被除数放在DX,AX中。其中DX为高位字,16位除数为源操作数,结果的16位端在AX中,16位余数在DX中。表示为
(AX)<-(DX,AX)/(SRC) 的商
(DX)<-(DX,AX)/(SRC) 的余数
双字操作:64位被除数在EDX,EAX中,其中EDX为高位双字,32位除数为源操作数,结果的32位商在EAX中,32位余数在EDX中,表示为
(EAX)<-(EDX,EAX)/(SRC) 的商
(EDX)<-(EDX,EAX)/(SRC) 的余数。
商和余数均为无符号数。
CBW,CWD //change byte word // change word dword
功能 : 有符号数扩展指令
格式 : CBW CWD
AAA,AAS,AAM,AAD
功能 : 非压 BCD 码运算调整指令
格式 : AAA AAS AAM AAD
影响标志 : A,C(AAA,AAS)S,Z,P(AAM,AAD)
DAA,DAS
功能 : 压缩 BCD 码调整指令
格式 : DAA DAS
影响标志 : C,P,A,Z,S
MOVSB,MOVSW,MOVSD
功能 : 字符串传送指令 移动数据 内存--》内存
格式 : MOVSB MOVSW MOVSD
标志位 : 无
movsb 把寄存机esi所存的地址的数据以字节复制到edi 复制完成后根据DF标志寄存器的值 0:将esi和edi + 1
movsw 把寄存机esi所存的地址的数据以word复制到edi 复制完成后根据DF标志寄存器的值 1:将esi和edi - 2
movsd 把寄存机esi所存的地址的数据以dword复制到edi 复制完成后根据DF标志寄存器的值 0:将esi和edi +4
CMPSB,CMPSW,CMPSD
功能 : 字符串比较指令
格式 : CMPSB CMPSWCMPSD
标志位 : C,P,Z,S,O
SCASB,SCASW //scansb
功能 : 字符串搜索指令
格式 : SCASB SCASW
标志位 : C,P,Z,S,O
LODSB,LODSW,STOSB,STOSW
功能 : 字符串载入或存贮指令
格式 : LODSB LODSWSTOSB STOS
标志位 : 无
STOS指令:将Al/AX/EAX的值存储到[EDI]指定的内存单元
STOS BYTE PTR ES:[EDI] 简写为STOSB
STOS WORD PTR ES:[EDI] 简写为STOSW
STOS DWORD PTR ES:[EDI] 简写为STOSD
具体是AL/AX/EAX那就要看具体的宽度是多少,STOS指令同样受标志寄存器D位的影响(Direction Flag),当D位为1的时候,EDI的值会减,当D位为0时,EDI的值会加,MOVS指令也是受D位影响
REP指令:按计数寄存器(ecx)中指定的次数重复执行字符串指令
mov ecx, 10
rep movsd
上面2句话的意思:rep movs dword ptr es:[edi], dword ptr ds:[esi] 执行16次每次复制4个字节
AND,OR,XOR,NOT,TEST
功能 : 执行 BIT 与 BIT 之间的逻辑运算
格 式 : AND r/m,r/m/dataOR r/m,r/m/data XOR r/m,r/m/data TEST
r/m,r/m/data NOT r/m
影响标志 : C,O,P,Z,S( 其中 C 与 O 两个标志会被设为 0) NOT 指令不影响任何标志位
test指令:对2个进行与运算但是不将结果保存到第一个数
SHR,SHL,SAR,SAL
功能 : 移位指令
格式 : SHR r/m,data/CLSHL r/m,data/CL SAR r/m,data/CL SAL r/m,data/CL
影响标志 : C,P,Z,S,O
ROR,ROL,RCR,RCL
功能 : 循环移位指令
格式 : ROR r/m,data/CLROL r/m,data/CL RCR r/m,data/CL RCL r/m,data/CL
影响标志 : C,P,Z,S,O
CLC,STC,CMC
功能 : 设定进位标志
格式 : CLC STC CMC
标志位 : C
CLD,STD
功能 : 设定方向标志
格式 : CLD STD
标志位 : D
CLI,STI
功能 : 设定中断标志
格式 : CLI STI
标志位 : I
CMP
功能 : 比较 OP1 与 OP2 的值 相当于sub指令但是不将结果保存到第一个数
格式 : CMP r/m,r/m/data
标志位 : C,P,A,Z,O
JMP
功能 : 跳往指定地址执行 无条件跳转
格式 : JMP 地址
JXX
功能 : 当特定条件成立则跳往指定地址执行
格式 : JXX 地址
XX 为下列值 :
A: ABOVE, 当 C=0,Z=0 时成立
B: BELOW, 当 C=1 时成立
C: CARRY, 当 CF=1 时成立
CXZ: CX 寄存器的值为 0(ZERO) 时成立
E: EQUAL, 当 Z=1 时成立
G: GREATER( 大于 ), 当 Z=0 且 S=0 时成立
L: LESS( 小于 ), 当 S 不为零时成立
N: NOT( 相反条件 ), 需和其它符号配合使用
O: OVERFLOW,O=1 时成立
P: PARITY,P=1 时成立
PE: PARITY EVEN,P=1 时成立
PO: PARITY ODD,P=0 时成立
S: SIGN,S=1 时成立
Z: ZERO,Z=1 时成立
LOOP
功能 : 循环指令集
语法 : LOOP 地址
LOOPE(Z)
格式: LOOPNE(Z) 地址
标志位 : 无
CALL,RET
功能 : 子程序调用 ,返回指令
语法 : CALL 地址 RET RET n
标志位 : 无
CALL指令会做2件事情,将CALL指令的下一个指令的地址PUSH到堆栈中,修改EIP的值为要调用函数的地址
RET 指令 会将当前栈顶的值给EIP,然后ESP+4
INT,IRET
功能 : 中断调用及返回指令
语法 : INT n IRET
标志位 : 在执行 INT 时,CPU 会自动将标志寄存器的值入栈 ,在执行 IRET 时则会将堆栈中
的标志值弹回寄存器
NOP
功能 : 空操作指令。不执行任何操作,但要花费 CPU 一个机器周期
格式 : NOP
HLT
功能 : 暂停指令。 CPU 不执行任何操作,一直处于暂停状态,但 IP 指向 HLT 的下一条指令。
格式 : HLT
cdq
cdq的作用无非就是将一个32位有符合数扩展为64位有符合数,数据能表示的数不变,具体是这样实现的,比如eax=fffffffb(值为-5),然后cdq把eax的最高位bit,也就是二进制1,全部复制到edx的每一个bit位,EDX 变成 FFFFFFFF,这时eax与edx连起来就是一个64位数,FFFFFFFF FFFFFFFB ,它是一个 64 bit 的大型数字,数值依旧是 -5。
(伪指令) | |||||
ORG
|
指明程序的开始位置
| ||||
DB
|
定义数据表
| ||||
DW
|
定义
16
位的地址表
| ||||
EQU
|
给一个表达式或一个字符串起名
| ||||
DATA
|
给一个
8
位的内部
RAM
起名
| ||||
XDATA
|
给一个
8
位的外部
RAM
起名
| ||||
BIT
|
给一个可位寻址的位单元起名
| ||||
END
|
指出源程序到此为止
|
(指令中的符号标识) | |||||
Rn
|
工作寄存器
R0-R7
| ||||
Ri
|
工作寄存器
R0
和
R1
| ||||
@Ri
|
间接寻址的
8
位
RAM
单元地址(
00H-FFH
)
| ||||
#data8
|
8
位常数
| ||||
#data16
|
16
位常数
| ||||
addr16
|
16
位目标地址,能转移或调用到
64KROM
的任何地方
| ||||
addr11
|
11
位目标地址,在下条指令的
2K
范围内转移或调用
| ||||
Rel
|
8
位偏移量,用于
SJMP
和所有条件转移指令,范围
-128
~
+127
| ||||
Bit
|
片内
RAM
中的可寻址位和
SFR
的可寻址位
| ||||
$
|
指本条指令的起始位置
|
助记符 |
指令说明
|
字节数
|
周期数
| ||
(数据传递类指令)
| |||||
MOV
|
A
,
Rn
|
寄存器传送到累加器
|
1
|
1
| |
MOV
|
A
,
direct
|
直接地址传送到累加器
|
2
|
1
| |
MOV
|
A
,
@Ri
|
累加器传送到外部
RAM(8
地址
|
1
|
1
| |
MOV
|
A
,
#data
|
立即数传送到累加器
|
2
|
1
| |
MOV
|
Rn
,
A
|
累加器传送到寄存器
|
1
|
1
| |
MOV
|
Rn
,
direct
|
直接地址传送到寄存器
|
2
|
2
| |
MOV
|
Rn
,
#data
|
累加器传送到直接地址
|
2
|
1
| |
MOV
|
direct
,
Rn
|
寄存器传送到直接地址
|
2
|
1
| |
MOV
|
direct
,
direct
|
直接地址传送到直接地址
|
3
|
2
| |
MOV
|
direct
,
A
|
累加器传送到直接地址
|
2
|
1
| |
MOV
|
direct
,
@Ri
|
间接
RAM
传送到直接地址
|
2
|
2
| |
MOV
|
direct
,
#data
|
立即数传送到直接地址
|
3
|
2
| |
MOV
|
@Ri
,
A
|
直接地址传送到直接地址
|
1
|
2
| |
MOV
|
@Ri
,
direct
|
直接地址传送到间接
RAM
|
2
|
1
| |
MOV
|
@Ri
,
#data
|
立即数传送到间接
RAM
|
2
|
2
| |
MOV
|
DPTR
,
#data16
|
16
位常数加载到数据指针
|
3
|
1
| |
MOVC
|
A
,
@A+DPTR
|
代码字节传送到累加器
|
1
|
2
| |
MOVC
|
A
,
@A+PC
|
代码字节传送到累加器
|
1
|
2
| |
MOVX
|
A
,
@Ri
|
外部
RAM(8
地址
)
传送到累加器
|
1
|
2
| |
MOVX
|
A
,
@DPTR
|
外部
RAM(16
地址
)
传送到累加器
|
1
|
2
| |
MOVX
|
@Ri
,
A
|
累加器传送到外部
RAM(8
地址
)
|
1
|
2
| |
MOVX
|
@DPTR
,
A
|
累加器传送到外部
RAM(16
地址
)
|
1
|
2
| |
PUSH
|
direct
|
直接地址压入堆栈
|
2
|
2
| |
POP
|
direct
|
直接地址弹出堆栈
|
2
|
2
| |
XCH
|
A,Rn
|
寄存器和累加器交换
|
1
|
1
| |
XCH
|
A, direct
|
直接地址和累加器交换
|
2
|
1
| |
XCH
|
A, @Ri
|
间接
RAM
和累加器交换
|
1
|
1
| |
XCHD
|
A, @Ri
|
间接
RAM
和累加器交换低
4
位字节
|
1
|
1
| |
(
算术运算类指令
)
| |||||
INC
|
A
|
累加器加
1
|
1
|
1
| |
INC
|
Rn
|
寄存器加
1
|
1
|
1
| |
INC
|
direct
|
直接地址加
1
|
2
|
1
| |
INC
|
@Ri
|
间接
RAM
加
1
|
1
|
1
| |
INC
|
DPTR
|
数据指针加
1
|
1
|
2
| |
DEC
|
A
|
累加器减
1
|
1
|
1
| |
DEC
|
Rn
|
寄存器减
1
|
1
|
1
| |
DEC
|
direct
|
直接地址减
1
|
2
|
2
| |
DEC
|
@Ri
|
间接
RAM
减
1
|
1
|
1
| |
MUL
|
AB
|
累加器和
B
寄存器相乘
|
1
|
4
| |
DIV
|
AB
|
累加器除以
B
寄存器
|
1
|
4
| |
DA
|
A
|
累加器十进制调整
|
1
|
1
| |
ADD
|
A,Rn
|
寄存器与累加器求和
|
1
|
1
| |
ADD
|
A,direct
|
直接地址与累加器求和
|
2
|
1
| |
ADD
|
A,#data
|
立即数与累加器求和
|
2
|
1
| |
ADD
|
A,@Ri
|
间接
RAM
与累加器求和
|
1
|
1
| |
ADDC
|
A,Rn
|
寄存器与累加器求和
(
带进位
)
|
1
|
1
| |
ADDC
|
A,direct
|
直接地址与累加器求和
(
带进位
)
|
2
|
1
| |
ADDC
|
A,@Ri
|
间接
RAM
与累加器求和
(
带进位
)
|
1
|
1
| |
ADDC
|
A,#data
|
立即数与累加器求和
(
带进位
)
|
2
|
1
| |
SUBB
|
A,Rn
|
累加器减去寄存器
(
带借位
)
|
1
|
1
| |
SUBB
|
A,direct
|
累加器减去直接地址
(
带借位
)
|
2
|
1
| |
SUBB
|
A,@Ri
|
累加器减去间接
RAM(
带借位
)
|
1
|
1
| |
SUBB
|
A,#data
|
累加器减去立即数
(
带借位
)
|
2
|
1
| |
(
逻辑运算类指令
)
| |||||
ANL
|
A,Rn
|
寄存器“与”到累加器
|
1
|
1
| |
ANL
|
A,direct
|
直接地址“与”到累加器
|
2
|
1
| |
ANL
|
A,@Ri
|
间接
RAM
“
与”到累加器
|
1
|
1
| |
ANL
|
A,#data
|
立即数“与”到累加器
|
2
|
1
| |
ANL
|
direct,A
|
累加器“与”到直接地址
|
2
|
1
| |
ANL
|
direct, #data
|
立即数“与”到直接地址
|
3
|
2
| |
ORL
|
A,Rn
|
寄存器“或”到累加器
|
1
|
2
| |
ORL
|
A,direct
|
直接地址“或”到累加器
|
2
|
1
| |
ORL
|
A,@Ri
|
间接
RAM
“
或”到累加器
|
1
|
1
| |
ORL
|
A,#data
|
立即数“或”到累加器
|
2
|
1
| |
ORL
|
direct,A
|
累加器“或”到直接地址
|
2
|
1
| |
ORL
|
direct, #data
|
立即数“或”到直接地址
|
3
|
1
| |
XRL
|
A,Rn
|
寄存器“异或”到累加器
|
1
|
2
| |
XRL
|
A,direct
|
直接地址“异或”到累加器
|
2
|
1
| |
XRL
|
A,@Ri
|
间接
RAM
“
异或”到累加器
|
1
|
1
| |
XRL
|
A,#data
|
立即数“异或”到累加器
|
2
|
1
| |
XRL
|
direct,A
|
累加器“异或”到直接地址
|
2
|
1
| |
XRL
|
direct, #data
|
立即数“异或”到直接地址
|
3
|
1
| |
CLR
|
A
|
累加器清零
|
1
|
2
| |
CPL
|
A
|
累加器求反
|
1
|
1
| |
RL
|
A
|
累加器循环左移
|
1
|
1
| |
RLC
|
A
|
带进位累加器循环左移
|
1
|
1
| |
RR
|
A
|
累加器循环右移
|
1
|
1
| |
RRC
|
A
|
带进位累加器循环右移
|
1
|
1
| |
SWAP
|
A
|
累加器高、低
4
位交换
|
1
|
1
| |
(
控制转移类指令
)
| |||||
JMP
|
@A+DPTR
|
相对
DPTR
的无条件间接转移
|
1
|
2
| |
JZ
|
rel
|
累加器为
0
则转移
|
2
|
2
| |
JNZ
|
rel
|
累加器为
1
则转移
|
2
|
2
| |
CJNE
|
A,direct,rel
|
比较直接地址和累加器
,
不相等转移
|
3
|
2
| |
CJNE
|
A,#data,rel
|
比较立即数和累加器
,
不相等转移
|
3
|
2
| |
CJNE
|
Rn,#data,rel
|
比较寄存器和立即数
,
不相等转移
|
2
|
2
| |
CJNE
|
@Ri,#data,rel
|
比较立即数和间接
RAM,
不相等转移
|
3
|
2
| |
DJNZ
|
Rn,rel
|
寄存器减
1,
不为
0
则转移
|
3
|
2
| |
DJNZ
|
direct,rel
|
直接地址减
1,
不为
0
则转移
|
3
|
2
| |
NOP
|
|
空操作
,
用于短暂延时
|
1
|
1
| |
ACALL
|
add11
|
绝对调用子程序
|
2
|
2
| |
LCALL
|
add16
|
长调用子程序
|
3
|
2
| |
RET
|
|
从子程序返回
|
1
|
2
| |
RETI
|
|
从中断服务子程序返回
|
1
|
2
| |
AJMP
|
add11
|
无条件绝对转移
|
2
|
2
| |
LJMP
|
add16
|
无条件长转移
|
3
|
2
| |
SJMP
|
rel
|
无条件相对转移
|
2
|
2
| |
(
布尔指令
)
| |||||
CLR
|
C
|
清进位位
|
1
|
1
| |
CLR
|
bit
|
清直接寻址位
|
2
|
1
| |
SETB
|
C
|
置位进位位
|
1
|
1
| |
SETB
|
bit
|
置位直接寻址位
|
2
|
1
| |
CPL
|
C
|
取反进位位
|
1
|
1
| |
CPL
|
bit
|
取反直接寻址位
|
2
|
1
| |
ANL
|
C,bit
|
直接寻址位“与”到进位位
|
2
|
2
| |
ANL
|
C
,
/bit
|
直接寻址位的反码“与”到进位位
|
2
|
2
| |
ORL
|
C,bit
|
直接寻址位“或”到进位位
|
2
|
2
| |
ORL
|
C
,
/bit
|
直接寻址位的反码“或”到进位位
|
2
|
2
| |
MOV
|
C,bit
|
直接寻址位传送到进位位
|
2
|
1
| |
MOV
|
bit, C
|
进位位位传送到直接寻址
|
2
|
2
| |
JC
|
rel
|
如果进位位为
1
则转移
|
2
|
2
| |
JNC
|
rel
|
如果进位位为
0
则转移
|
2
|
2
| |
JB
|
bit
,
rel
|
如果直接寻址位为
1
则转移
|
3
|
2
| |
JNB
|
bit
,
rel
|
如果直接寻址位为
0
则转移
|
3
|
2
| |
JBC
|
bit
,
rel
|
直接寻址位为
1
则转移并清除该位
|
2
|
2
|
bit 内部数据 RAM(20H ~ 2FH) ,特殊功能寄存器的直接地址的位指令介绍指令 字节 周期 动作说明算数运算指令 1. ADD A,Rn 1 1 将累加器与寄存器的内容相加,结果存回累加器 2. ADD A,direct 2 1 将累加器与直接地址的内容相加,结果存回累加器 3. ADD A,@Ri 1 1 将累加器与间接地址的内容相加,结果存回累加器 4. ADD A,#data 2 1 将累加器与常数相加,结果存回累加器 5. ADDC A,Rn 1 1 将累加器与寄存器的内容及进位 C 相加,结果存回累加器 6. ADDC A,direct 2 1 将累加器与直接地址的内容及进位 C 相加,结果存回累加器 7. ADDC A,@Ri 1 1 将累加器与间接地址的内容及进位 C 相加,结果存回累加器 8. ADDC A,#data 2 1 将累加器与常数及进位 C 相加,结果存回累加器 9. SUBB A,Rn 1 1 将累加器的值减去寄存器的值减借位 C,结果存回累加器 10. SUBB A,direct 2 1 将累加器的值减直接地址的值减借位 C,结果存回累加器 11. SUBB A,@Ri 1 1 将累加器的值减间接地址的值减借位 C,结果存回累加器 12. SUBB A,#data 2 1 将累加器的值减常数值减借位 C,结果存回累加器 13. INC A 1 1 将累加器的值加 1 14. INC Rn 1 1 将寄存器的值加 l 15. INC direct 2 1 将直接地址的内容加 1 16. INC @Ri 1 1 将间接地址的内容加 1 17. INC DPTR 1 1 数据指针寄存器值加 1 说明:将 16 位的 DPTR 加 1,当 DPTR 的低字节 (DPL) 从 FFH 溢出至 00H 时,会使高字节(DPH) 加 1,不影响任何标志位 18. DEC A 1 1 将累加器的值减 1 19. DEC Rn 1 1 将寄存器的值减 1 20. DEC direct 2 1 将直接地址的内容减 1 21. DEC @Ri 1 1 将间接地址的内容减 1 22. MUL AB 1 4 将累加器的值与 B 寄存器的值相乘,乘积的低位字节存回累加器,高位字节存回 B 寄存器 说明:将累加器 A 和寄存器 B 内的无符号整数相乘,产生 16 位的积,低位字节存入 A,高位字节存入 B 寄存器 。 如果积大于 FFH, 则溢出标志位 (OV) 被设定为 1, 而进位标志位为 0 23. DIV AB 1 4 将累加器的值除以 B 寄存器的值,结果的商存回累加器,余数存回 B 寄存器 说明:无符号的除法运算,将累加器 A 除以 B 寄存器的值,商存入 A,余数存入 B。执行本指令后,进位位 (C)及溢出位 (OV) 被清除为 0 24. DA A 1 1 将累加器 A 作十进制调整, 若(A) 3-0>9 或(AC)=1 ,则 (A) 3- 0←(A)3 -0+6 若(A) 7-4>9 或 (C)=1 ,则 (A) 7- 4←(A)7 -4+6 逻辑运算指令 25. ANL A,Rn 1 1 将累加器的值与寄存器的值做 AND 的逻辑判断,结果存回累加器 26. ANL A,direct 2 1 将累加器的值与直接地址的内容做 AND 的逻辑判断,结果存回累加器 27. ANL A,@Ri 1 1 将累加器的值与间接地址的内容做 AND 的逻辑判断,结果存回累加器 28. ANL A,#data 2 1 将累加器的值与常数做 AND 的逻辑判断,结果存回累加器 29. ANL direct,A 2 1 将直接地址的内容与累加器的值做 AND 的逻辑判断,结果存回该直接地址 30. ANL direct,#data 3 2 将直接地址的内容与常数值做 AND 的逻辑判断,结果存回该直接地址 31. ORL A,Rn 1 1 将累加器的值与寄存器的值做 OR 的逻辑判断,结果存回累加器 32. ORL A,direct 2 1 将累加器的值与直接地址的内容做 OR 的逻辑判断,结果存回累加器 33. ORL A,@Ri 1 1 将累加器的值与间接地址的内容做 OR 的逻辑判断,结果存回累加器 34. ORL A,#data 2 1 将累加器的值与常数做 OR 的逻辑判断,结果存回累加器 35. ORL direct,A 2 1 将直接地址的内容与累加器的值做 OR 的逻辑判断,结果存回该直接地址 36. ORL direct,#data 3 2 将直接地址的内容与常数值做 OR 的逻辑判断,结果存回该直接地址 37. XRL A,Rn 1 1 将累加器的值与寄存器的值做 XOR 的逻辑判断,结果存回累加器 38. XRL A,direct 2 1 将累加器的值与直接地址的内容做 XOR 的逻辑判断,结果存回累加器 39. XRL A,@Ri 1 1 将累加器的值与间接地扯的内容做 XOR 的逻辑判断,结果存回累加器 40. XRL A,#data 2 1 将累加器的值与常数作 XOR 的逻辑判断,结果存回累加器 41. XRL direct,A 2 1 将直接地址的内容与累加器的值做 XOR 的逻辑判断,结果存回该直接地址 42. XRL direct,#data 3 2 将直接地址的内容与常数的值做 XOR 的逻辑判断,结果存回该直接地址 43. CLR A 1 1 清除累加器的值为 0 44. CPL A 1 1 将累加器的值反相 45. RL A 1 1 将累加器的值左移一位 46. RLC A 1 1 将累加器含进位 C 左移一位 47. RR A 1 1 将累加器的值右移一位 48. RRC A 1 1 将累加器含进位 C 右移一位 49. SWAP A 1 1 将累加器的高 4 位与低 4 位的内容交换。 (A)3- 0←(A)7 -4数据转移指令 50. MOV A,Rn 1 1 将寄存器的内容载入累加器 51. MOV A,direct 2 1 将直接地址的内容载入累加器 52. MOV A,@Ri 1 1 将间接地址的内容载入累加器 53. MOV A,#data 2 1 将常数载入累加器 54. MOV Rn , A 1 1 将累加器的内容载入寄存器 55. MOV Rn,direct 2 2 将直接地址的内容载入寄存器 56. MOV Rn,gdata 2 1 将常数载入寄存器 57. MOV direct,A 2 1 将累加器的内容存入直接地址 58. MOV direct,Rn 2 2 将寄存器的内容存入直接地址 59. MOV direct1, direct2 3 2 将直接地址 2 的内容存入直接地址 1 60. MOV direct,@Ri 2 2 将间接地址的内容存入直接地址 61. MOV direct,#data 3 2 将常数存入直接地址 62. MOV @Ri,A 1 1 将累加器的内容存入某间接地址 63. MOV @Ri,direct 2 2 将直接地址的内容存入某间接地址 64. MOV @Ri,#data 2 1 将常数存入某间接地址 65. MOV DPTR,#data16 3 2 将 16 位的常数存入数据指针寄存器 66. MOVC A,@A+DPTR 1 2 (A) ←((A)+(DPTR)) 累加器的值再加数据指针寄存器的值为其所指定地址,将该地址的内容读入累加器 67. MOVC A,@A+PC 1 2 (PC)←(PC)+1 ; (A) ←((A)+(PC)) 累加器的值加程序计数器的值作为其所指定地址,将该地址的内容读入累加器 68. MOVX A,@Ri 1 2 将间接地址所指定外部存储器的内容读入累加器 (8 位地址 ) 69. MOVX A,@DPTR 1 2 将数据指针所指定外部存储器的内容读入累加器 (16 位地址 ) 70. MOVX @Ri,A 1 2 将累加器的内容写入间接地址所指定的外部存储器 (8 位地址 ) 71. MOVX @DPTR,A 1 2 将累加器的内容写入数据指针所指定的外部存储器 (16 位地址 ) 72. PUSH direct 2 2 将直接地址的内容压入堆栈区 73. POP direct 2 2 从堆栈弹出该直接地址的内容 74. XCH A,Rn 1 1 将累加器的内容与寄存器的内容互换 75. XCH A,direct 2 1 将累加器的值与直接地址的内容互换 76. XCH A,@Ri 1 1 将累加器的值与间接地址的内容互换 77. XCHD A,@Ri 1 1 将累加器的低 4 位与间接地址的低 4 位互换布尔代数运算 78. CLR C 1 1 清除进位 C 为 0 79. CLR bit 2 1 清除直接地址的某位为 0 80. SETB C 1 1 设定进位 C 为 1 81. SETB bit 2 1 设定直接地址的某位为 1 82. CPL C 1 1 将进位 C 的值反相 83. CPL bit 2 1 将直接地址的某位值反相 84. ANL C,bit 2 2 将进位 C 与直接地址的某位做 AND 的逻辑判断,结果存回进位 C 85. ANL C,/bit 2 2 将进位 C 与直接地址的某位的反相值做 AND 的逻辑判断,结果存回进位 C 86. ORL C,bit 2 2 将进位 C 与直接地址的某位做 OR 的逻辑判断,结果存回进位 C 87. ORL C,/bit 2 2 将进位 C 与直接地址的某位的反相值做 OR 的逻辑判断,结果存回进位 C 88. MOV C,bit 2 1 将直接地址的某位值存入进位 C 89. MOV bit,C 2 2 将进位 C 的值存入直接地址的某位 90. JC rel 2 2 若进位 C=1 则跳至 rel 的相关地址 91. JNC rel 2 2 若进位 C=0 则跳至 rel 的相关地址 92. JB bit,rel 3 2 若直接地址的某位为 1,则跳至 rel 的相关地址 93. JNB bit,rel 3 2 若直接地址的某位为 0,则跳至 rel 的相关地址 94. JBC bit,rel 3 2 若直接地址的某位为 1,则跳至 rel 的相关地址,并将该位值清除为 0程序跳跃 95. ACALL addr11 2 2 调用 2K 程序存储器范围内的子程序 96. LCALL addr16 3 2 调用 64K 程序存储器范围内的子程序 97. RET 1 2 从子程序返回 98. RETI 1 2 从中断子程序返回 99. AJMP addr11 2 2 绝对跳跃 (2K 内) 100 . LJMP addr16 3 2 长跳跃 (64K 内) 101 . SJMP rel 2 2 短跳跃 (2K 内)-128 ~ +127 字节 102 . JMP @A+DPTR 1 2 跳至累加器的内容加数据指针所指的相关地址 103 . JZ rel 2 2 累加器的内容为 0,则跳至 rel 所指相关地址104 . JNZ rel 2 2累加器的内容不为0,则跳至 rel 所指相关地址105 . CJNE A,direct,rel32 将累加器的内容与直接地址的内容比较,不相等则跳至rel 所指的相关地址106 . CJNE A,#data,rel 32将累加器的内容与常数比较,若不相等则跳至rel 所指的相关地址107. CJNE @Rn,#data,rel3 2将寄存器的内容与常数比较,若不相等则跳至rel 所指的相关地址108 . CJNE@Ri,#data,rel3 2将间接地址的内容与常数比较,若不相等则跳至rel 所指的相关地址109 . DJNZ Rn,rel 2 2将寄存器的内容减1,不等于0 则跳至 rel 所指的相关地址110 . DJNZ direct,rel 32将直接地址的内容减1,不等于0 则跳至 rel 所指的相关地址111 . NOP 1 1无动作 |
跳转指令
基于零标志位、进位标志位、溢出标志位、奇偶标志位和符号标志位的跳转
助记符 | 说明 | 标志位/寄存器 | 助记符 | 说明 | 标志位/寄存器 |
---|---|---|---|---|---|
JZ | 为零跳转 | ZF=1 | JNO | 无溢出跳转 | OF=0 |
JNZ | 非零跳转 | ZF=0 | JS | 有符号跳转 | SF=1 |
JC | 进位跳转 | CF=1 | JNS | 无符号跳转 | SF=0 |
JNC | 无进位跳转 | CF=0 | JP | 偶校验跳转 | PF=1 |
JO | 溢出跳转 | OF=1 | JNP | 奇校验跳转 | PF=0 |
相等性的比较
下表列出了基于相等性评估的跳转指令。有些情况下,进行比较的是两个操作数;其他情况下,则是基于 CX、ECX 或 RCX 的值进行跳转。表中符号 leftOp 和 rightOp 分别指的是 CMP 指令中的左(目的)操作数和右(源)操 作数:
助记符 | 说明 |
---|---|
JE | 相等跳转 (leftOp=rightOp) |
JNE | 不相等跳转 (leftOp M rightOp) |
JCXZ | CX=0 跳转 |
JECXZ | ECX=0 跳转 |
JRCXZ | RCX=0 跳转(64 位模式) |
无符号数比较
基于无符号数比较的跳转如下表所示。操作数的名称反映了表达式中操作数的顺序(比如 leftOp < rightOp)。下表中的跳转仅在比较无符号数值时才有意义。有符号操作数使用不同的跳转指令。
助记符 | 说明 | 助记符 | 说明 |
---|---|---|---|
JA | 大于跳转(若 leftOp > rightOp) | JB | 小于跳转(若 leftOp < rightOp) |
JNBE | 不小于或等于跳转(与 JA 相同) | JNAE | 不大于或等于跳转(与 JB 相同) |
JAE | 大于或等于跳转(若 leftOp ≥ rightOp) | JBE | 小于或等于跳转(若 leftOp ≤ rightOp) |
JNB | 不小于跳转(与 JAE 相同) | JNA | 不大于跳转(与 JBE 相同) |
有符号数比较
下表列岀了基于有符号数比较的跳转。下面的指令序列展示了两个有符号数值的比较:
助记符 | 说明 | 助记符 | 说明 |
---|---|---|---|
JG | 大于跳转(若 leftOp > rightOp) | JL | 小于跳转(若 leftOp < rightOp) |
JNLE | 不小于或等于跳转(与 JG 相同) | JNGE | 不大于或等于跳转(与 JL 相同) |
JGE | 大于或等于跳转(若 leftOp ≥ rightOp) | JLE | 小于或等于跳转(若 leftOp ≤ rightOp) |
JNL | 不小于跳转(与 JGE 相同) | JNG | 不大于跳转(与 JLE 相同) |
跳转相关的标志位:
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|
OF | DF | IF | TF | SF | ZF | AF | PF | CF | |||
溢 出 | 符 号 | 零 | 未 用 | 辅 助 | 未 用 | 奇 偶 | 未 用 | 进 位 |
助记符 | 条件( 执行 CMP A,B 之后的标志位) | 表达式 | |
无符号数 | JB/JNAE | CF=1 | A < B |
JAE/JNB | CF=0 | A ≥ B | |
JA/JNBE | CF=0 and ZF=0 | A > B | |
JBE/JNA | CF=1 or ZF=1 | A ≤ B | |
有符号数 | JL/JNGE | SF ≠ OF | A < B |
JGE/JNL | SF=OF | A ≥ B | |
JG/JNLE | SF=OF and ZF=0 | A > B | |
JLE/JNG | SF ≠ OF or ZF=1 | A ≤ B | |
无符号数或有符号数 | JZ/JE | ZF=1 | A = B |
名称 | 功能 | 操作数 | 操作码 | 模数 | 寄存器1 | 寄存器2 或内存 | 位移量 | 立即数 | 符号 | 方向 | 芯片 型号 | 16位 | 32位 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
JO | 溢出跳转 | 短 | $70 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNO | 不溢出跳转 | 短 | $71 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JB | 低于跳转 | 短 | $72 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNB | 不低于跳转 | 短 | $73 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JE | 相等跳转 | 短 | $74 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNE | 不等跳转 | 短 | $75 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JBE | 不高于跳转 | 短 | $76 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JA | 高于跳转 | 短 | $77 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JS | 负号跳转 | 短 | $78 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNS | 非负跳转 | 短 | $79 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JP | 奇偶跳转 | 短 | $7A | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNP | 非奇偶跳转 | 短 | $7B | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JL | 小于跳转 | 短 | $7C | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNL | 不小于跳转 | 短 | $7D | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JNG | 不大于跳转 | 短 | $7E | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JG | 大于跳转 | 短 | $7F | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JO | 溢出跳转 | 近 | $0F80 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNO | 不溢出跳转 | 近 | $0F81 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JB | 低于跳转 | 近 | $0F82 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNB | 不低于跳转 | 近 | $0F83 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JE | 相等跳转 | 近 | $0F84 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNE | 不等跳转 | 近 | $0F85 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JBE | 不高于跳转 | 近 | $0F86 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JA | 高于跳转 | 近 | $0F87 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JS | 负号跳转 | 近 | $0F88 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNS | 非负跳转 | 近 | $0F89 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JP | 奇偶跳转 | 近 | $0F8A | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNP | 非奇偶跳转 | 近 | $0F8B | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JL | 小于跳转 | 近 | $0F8C | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNL | 不小于跳转 | 近 | $0F8D | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JNG | 不大于跳转 | 近 | $0F8E | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JG | 大于跳转 | 近 | $0F8F | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | 无 | $66 |
JO | 溢出跳转 | 近 | $0F80 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNO | 不溢出跳转 | 近 | $0F81 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JB | 低于跳转 | 近 | $0F82 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNB | 不低于跳转 | 近 | $0F83 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JE | 相等跳转 | 近 | $0F84 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNE | 不等跳转 | 近 | $0F85 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JBE | 不高于跳转 | 近 | $0F86 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JA | 高于跳转 | 近 | $0F87 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JS | 负号跳转 | 近 | $0F88 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNS | 非负跳转 | 近 | $0F89 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JP | 奇偶跳转 | 近 | $0F8A | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNP | 非奇偶跳转 | 近 | $0F8B | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JL | 小于跳转 | 近 | $0F8C | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNL | 不小于跳转 | 近 | $0F8D | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JNG | 不大于跳转 | 近 | $0F8E | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JG | 大于跳转 | 近 | $0F8F | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JCXZ | 计数一六零跳转 | 位移8 | $E3 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | $67 |
JECXZ | 计数三二零跳转 | 位移8 | $E3 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $67 | 无 |
JMP | 跳转 | 寄16 | $FF | 11 | 100 | 3 | 无 | 无 | 无 | 无 | 8086 | 无 | $66 |
JMP | 跳转 | 寄32 | $FF | 11 | 100 | 3 | 无 | 无 | 无 | 无 | 386 | $66 | 无 |
JMP | 跳转 | 16[寄16] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 32[寄16] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 16[寄32] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 32[寄32] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 16[寄16+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 32[寄16+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 16[寄32+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 32[寄32+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 16[寄16+位移16] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 32[寄16+位移16] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 16[寄32+位移32] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 32[寄32+位移32] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 近16[寄16] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 近32[寄16] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 近16[寄32] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 近32[寄32] | $FF | 00 | 100 | 5 | 无 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 近16[寄16+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 近32[寄16+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 近16[寄32+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 近32[寄32+位移8] | $FF | 01 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 近16[寄16+位移16] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 近32[寄16+位移16] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 近16[寄32+位移32] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 近32[寄32+位移32] | $FF | 10 | 100 | 5 | 9 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 远16[寄16] | $FF | 00 | 101 | 5 | 无 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 远32[寄16] | $FF | 00 | 101 | 5 | 无 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 远16[寄32] | $FF | 00 | 101 | 5 | 无 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 远32[寄32] | $FF | 00 | 101 | 5 | 无 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 远16[寄16+位移8] | $FF | 01 | 101 | 5 | 9 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 远32[寄16+位移8] | $FF | 01 | 101 | 5 | 9 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 远16[寄32+位移8] | $FF | 01 | 101 | 5 | 9 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 远32[寄32+位移8] | $FF | 01 | 101 | 5 | 9 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 远16[寄16+位移16] | $FF | 10 | 101 | 5 | 9 | 无 | 无 | 无 | 8086 | 无 | $6766 |
JMP | 跳转 | 远32[寄16+位移16] | $FF | 10 | 101 | 5 | 9 | 无 | 无 | 无 | 386 | $66 | $67 |
JMP | 跳转 | 远16[寄32+位移32] | $FF | 10 | 101 | 5 | 9 | 无 | 无 | 无 | 386 | $67 | $66 |
JMP | 跳转 | 远32[寄32+位移32] | $FF | 10 | 101 | 5 | 9 | 无 | 无 | 无 | 386 | $6766 | 无 |
JMP | 跳转 | 短 | $EB | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | 无 |
JMP | 跳转 | 位移16 | $E9 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | $66 |
JMP | 跳转 | 位移32 | $E9 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JMP | 跳转 | 近 | $E9 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | $66 |
JMP | 跳转 | 近 | $E9 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JMP | 跳转 | 远(数段址:)偏移16 | $EA | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 8086 | 无 | $66 |
JMP | 跳转 | 远(数段址:)偏移32 | $EA | 无 | 无 | 无 | 无 | 10 | 无 | 无 | 386 | $66 | 无 |
JMP | 跳转 | 数段址:偏移16 | $EA | 无 | 无 | 无 | 无 | 12 | 无 | 无 | 8086 | 无 | $66 |
JMP | 跳转 | 数段址:偏移32 | $EA | 无 | 无 | 无 | 无 | 12 | 无 | 无 | 386 | $66 | 无 |
JMPE | 跳转扩展 | 寄16 | $0F00 | 11 | 110 | 3 | 无 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 寄32 | $0F00 | 11 | 110 | 3 | 无 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 16[寄16] | $0F00 | 00 | 110 | 5 | 无 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 32[寄16] | $0F00 | 00 | 110 | 5 | 无 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 16[寄32] | $0F00 | 00 | 110 | 5 | 无 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 32[寄32] | $0F00 | 00 | 110 | 5 | 无 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 16[寄16+位移8] | $0F00 | 01 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 32[寄16+位移8] | $0F00 | 01 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 16[寄32+位移8] | $0F00 | 01 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 32[寄32+位移8] | $0F00 | 01 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 16[寄16+位移16] | $0F00 | 10 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 32[寄16+位移16] | $0F00 | 10 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 16[寄32+位移32] | $0F00 | 10 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 32[寄32+位移32] | $0F00 | 10 | 110 | 5 | 9 | 无 | 无 | 无 | IA64 | $66 | 无 |
JMPE | 跳转扩展 | 位移16 | $0FB8 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | IA64 | 无 | $66 |
JMPE | 跳转扩展 | 位移32 | $0FB8 | 无 | 无 | 无 | 无 | 10 | 无 | 无 | IA64 | $66 | 无 |
短转移指令机器码计算
004013F6 | 80FB 2A | cmp bl,2A | 2A:'*'
004013F9 | 75 23 | jne switch.40141E |
004013FB | 8D45 10 | lea eax,dword ptr ss:[ebp+10] |
004013FE | 50 | push eax |
004013FF | E8 42070000 | call switch.401B46 |
00401404 | 85C0 | test eax,eax |
00401406 | 59 | pop ecx |
00401407 | 8945 D8 | mov dword ptr ss:[ebp-28],eax | [ebp-28]:EntryPoint
0040140A | 0F8D 5F060000 | jge switch.401A6F |
00401410 | 834D FC 04 | or dword ptr ss:[ebp-4],4 |
00401414 | F7D8 | neg eax |
00401416 | 8945 D8 | mov dword ptr ss:[ebp-28],eax | [ebp-28]:EntryPoint
00401419 | E9 51060000 | jmp switch.401A6F |
0040141E | 8B45 D8 | mov eax,dword ptr ss:[ebp-28] | [ebp-28]:EntryPoint
00401421 | 0FBECB | movsx ecx,bl |
00401424 | 8D0480 | lea eax,dword ptr ds:[eax+eax*4] |
00401427 | 8D4441 D0 | lea eax,dword ptr ds:[ecx+eax*2-30] |
004013F9 | 75 23 | jne switch.40141E
75是jne短转移的机器码,7500H - 757F是向后转移,7580H - 75FFH是向前转移,这里75 23应该是向后转移23H
CPU执行jne 40141E之后eip的值为004013F9+2(指令长度) = 4013FB 然后加上转移量23H 得出40141E
公式如下
位移量 = 目的地址 - 起始地址 - 跳转指令本身的长度
转移指令机器码 = 转移类别机器码 + 位移量
长转移指令机器码计算
004013E8 | E9 82060000 | jmp switch.401A6F |
jmp 401A6F
目的地址 - 起始地址 - 跳转指令本身的长度 = 位移量
401A6F - 004013E8 - 5 = 682H
对应机器码 E9 82060000
堆栈平衡
一个方法对应一个方法栈,下面见图
先传入了一个参数1,从右到左的传参数,在调用call的方法内存地址,然后,她会先把下一行执行的代码push进栈中,也就是下一行的地址:0020142c
最后的add esp,4,其实就是我们刚刚给栈中传入了一个参数,所以咱们得维护栈的平衡
咱们看看方法内部
先保存上一个方法的栈底指针,
push ebp
在把上一个方法的栈顶指针作为这个方法的栈底指针,mov ebp,esp
sub esp,0d8 在给本方法分配局部变量的大小
mov eax,dword ptr ss:[ebp+8] 把上一个,也就是传进入的参数赋值给eax
这里[ebp] = 上一个方法的ebp [ebp + 4] 该方法返回地址
最后在 mov esp,ebp. 把这个方法的栈底指针分配给栈顶指针
pop ebp 在把保存的栈底指针分配给ebp
retn 这句话其实是:pop eip 把eip的地址改变
调用约定
常用的调用约定分为四种:
_stdcall(windowsAPI默认调用方式):参数压栈方式右到左,函数内平衡,函数结束ret xxx
_cdecl(c/c++默认调用方式):参数压栈方式右到左,函数外平衡堆栈,call后面跟着add esp,xxx
_fastcall:参数压栈方式右到左,寄存器方式传参,函数内平衡堆栈
_thiscall:参数压栈方式右到左,ecx传递this指针,函数内平衡堆栈