通用寄存器
寄存器 | 编号(二进制) | 编号(十进制) | ||
---|---|---|---|---|
32位 | 16位 | 8位 | ||
EAX | AX | AL | 000 | 0 |
ECX | CX | CL | 001 | 1 |
EDX | DX | DL | 010 | 2 |
EBX | BX | BL | 011 | 3 |
ESP | SP | AH | 100 | 4 |
EBP | BP | CH | 101 | 5 |
ESI | SI | DH | 110 | 6 |
EDI | DI | BH | 111 | 7 |
寄存器结构
(AX在EAX中,AH和AL在AX中)
31 16 | 15 8 | 7 0 |
---|---|---|
EAX | AX(AH) | AL |
ECX | CX(CH) | CL |
EDX | DX(DH) | DL |
EBX | BX(BH) | BL |
ESP | SP | |
EBP | BP | |
ESI | SI | |
EDI | DI |
运算指令
ADD
两边不能同时为内存
ADC:带进位加法
两边不能同时为内存,宽度要一样
C:carry带
ADC AL,CL --------AL=AL+CL+CF
ADC BYTE PTR DS:[12FFC4],2
ADC BYTE PTR DS:[12FFC4],AL
SBB:带借位减法
两边不能同时为内存,宽度要一样
B:borrow借
SBB AL,CL --------AL=AL-CL-CF
SBB BYTE PTR DS:[12FFC4],2
SBB BYTE PTR DS:[12FFC4],AL
XCHG:交换数据
两边不能同时为内存,宽度要一样
XCHG AL,CL
XCHG BYTE PTR DS:[12FFC4],EAX
XCHG BYTE PTR DS:[12FFC4],AL
MOVS:移动数据
内存-内存
MOVS BYTE PTR ES:[EDI],BYTE PTR ES:[ESI] 简写为MOVSB
在ESI存的地址里面取出一个字节给内存编号为EDI值的地方
移动后:若DF=0 ESI+=1 EDI+=1 若DF=1 ESI-=1 EDI-=1
MOVS WORD PTR ES:[EDI],WORD PTR ES:[ESI] 简写为MOVSW
移动后:若DF=0 ESI+=2 EDI+=2 若DF=1 ESI-=2 EDI-=2
MOVS DWORD PTR ES:[EDI],DWORD PTR ES:[ESI] 简写为MOVSD
移动后:若DF=0 ESI+=4 EDI+=4 若DF=1 ESI-=4 EDI-=4
STOS指令
将AL/AX/EAX/的值储存到[EDI]指定的内存单元
STOS BYTE PTR ES:[EDI] 简写为STOSB
移动后:若DF=0 EDI-=1 若DF=1 EDI+=1
STOS WORD PTR ES:[EDI] 简写为STOSW
移动后:若DF=0 EDI-=2 若DF=1 EDI+=2
STOS DWORD PTR ES:[EDI] 简写为STOSD
移动后:若DF=0 EDI-=4 若DF=1 EDI+=4
REP指令
按计数寄存器(ECX)中指定的次数重复执行字符串指令
MOV ECX,10
REP MOVSD 重复16次movsd操作
REP STOSD
JCC
JMP
唯一作用是无条件修改EIP的值,没有对栈和寄存器产生影响。
JMP 寄存器/立即数
本质是MOV EIP,寄存器/立即数,EIP只能由JMP指令修改
CALL
PUSH 地址B
MOV EIP,地址A/寄存器 简写为:CALL 地址A/寄存器
第一个作用和JMP一样,MOV EIP,寄存器/立即数。
第二个作用,把CALL指令的写一个指令地址push到栈顶(修改ESP)
CALL指令还没执行,怎么知道下一行指令的地址?
根据CALL指令占用的数据宽度,加偏移量去算,比如CALL这条指令,地址0X004183D7中数据为E8 21 00 00 00,有5个字节,下一行指令的地址就是地址偏移5
RET指令
本质是POP EIP
RET指令通常和CALL成对出现,把CALL压栈的地址POP EIP,让程序回归原来的流程
LEA ESP,[ESP+4]
MOV EIP,[ESP-4] 简写为:RET
CMP指令
指令格式:CMP R/M,R/M/IMM 两边不能同时为内存
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的。当两个操作数相等的时候,零标志位置1
TEST 指令
指令格式:TEST R/M,R/M/IMM 两边不能同时为内存
该指令在一定程序上和CMP指令时类似,两个数值进行与操作,结果不保存,但是会改变相应标志位
与操作:1 and 1 =1;1 and 0 = 0; 0 and 1 = 0; 0 and 0 = 0
常见用法:用这个指令可以确定某个寄存器是否等于0
TEST EAX,EAX 观察Z位
其他
JCC指令只看标志寄存器
所有JCC指令的动作->根据标志寄存器修改EIP的值
JCC指令 | 中文含义 | 英文原意 | 检查符号位 | 典型C应用 |
---|---|---|---|---|
JZ/JE | 若为0则跳转;若相等则跳转 | jump if zero;jump if equal | ZF=1 | if (i == j);if (i == 0); |
JNZ/JNE | 若不为0则跳转;若不相等则跳转 | jump if not zero;jump if not equal | ZF=0 | if (i != j);if (i != 0); |
JS | 若为负则跳转 | jump if sign | SF=1 | if (i < 0); |
JNS | 若为正则跳转 | jump if not sign | SF=0 | if (i > 0); |
JP/JPE | 若1出现次数为偶数则跳转 | jump if Parity (Even) | PF=1 | |
JNP/JPO | 若1出现次数为奇数则跳转 | jump if not parity (odd) | PF=0 | |
JO | 若溢出则跳转 | jump if overflow | OF=1 | |
JNO | 若无溢出则跳转 | jump if not overflow | OF=0 | |
JC/JB/JNAE | 若进位则跳转;若低于则跳转;若不高于等于则跳转 | jump if carry;jump if below;jump if not above equal | CF=1 | if (i < j); |
JNC/JNB/JAE | 若无进位则跳转;若不低于则跳转;若高于等于则跳转 | jump if not carry;jump if not below;jump if above equal | CF=0 | if (i >= j); |
JBE/JNA | 若低于等于则跳转;若不高于则跳转 | jump if below equal;jump if not above | ZF=1或CF=1 | if (i <= j); |
JNBE/JA | 若不低于等于则跳转;若高于则跳转 | jump if not below equal;jump if above | ZF=0或CF=0 | if (i > j); |
JL/JNGE | 若小于则跳转;若不大于等于则跳转 | jump if less;jump if not greater equal | SF != OF | if (si < sj); |
JNL/JGE | 若不小于则跳转;若大于等于则跳转; | jump if not less;jump if greater equal | SF = OF | if (si >= sj); |
JLE/JNG | 若小于等于则跳转;若不大于则跳转 | jump if less equal;jump if not greater | ZF != OF 或 ZF=1 | if (si <= sj); |
JNLE/JG | 若不小于等于则跳转;若大于则跳转 | jump if not less equal;jump if greater | SF=0F 且 ZF=0 | if(si>sj) |
更详细参考:https://www.jb51.net/article/178949.htm
寻址公式
如果寻的地址超过32位(FFFFFFFF),则就取FFFFFFFF的值
公式一
[立即数]
读取内存的值:
MOV EAX,DWORD PTR DS:[0x1234FF]
向内存中写入数据
MOV DWORD PRT DS:[0x1234FF],EAX
获取内存编号
LEA EAX,DWORD PTR DS:[0x1234FF]
公式二[reg]
reg代表寄存器,可以是8个通用寄存器中的任意一个
读取内存的值
MOV ESP,DWORD PTR DS:[EBP]
向内存中写入数据
MOV DWORD PTR DS:[EBP],ESP
公式三[reg+立即数]
读取内存的值:
mov ecx ,0x1234FF
mov eax,dword ptr ds:[ecx+4]
向内存中写入数据:
mov edx,0x1234FF
mov dword ptr ds:[edx+0xC],0x87654321
获取内存编号:
lea eax,dword ptr ds:[edx+4] —eax和edx+4(地址)相等
mov eax,dword ptr ds:[edx+4] --eax和edx+4(数值)相等
公式四[reg+reg*{1,2,4,8}]
读取内存的值:
MOV EAX,1234FF
MOV ECX,2
MOV EDX,DWORD PTR DS:[EAX+EDX*4]
向内存中写入数据
MOV EAX,1234FF
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*2],87654321
获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4]
公式五[reg+reg*{1,2,4,8}+立即数]
读取内存的值:
MOV EAX,1234FF
MOV ECX,2
MOV EDX,DWORD PTR DS:[EAX+EDX*4+1]
向内存中写入数据
MOV EAX,1234FF
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*2+1],87654321
获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4+1]
堆栈
Top栈顶,Base栈底
ESP存栈顶指针,EBP栈底
压入数据
MOV EBX,1234FF BASE
MOV EDX.1234FF TOP
栈顶减4
方式一:
MOV DWORD PTR DS:[EDX-4],0xAAAAAAAA
SUB EDX,4
方式二:
SUB EDX,4
MOV DWORD PTR DS:[EDX],0xBBBBBBBB
方式三:
MOV DWORD PTR DS:[EDX-4],0xCCCCCCCC
LEA EDX,DWORD PTR DS:[EDX-4]
方式四:
LEA EDX,DWORD PTR DS:[EDX-4]
MOV DWORD PTR DS:[EDX],0xEEEEEEEE
读取数据
方式一:通过base加偏移来读取
读第一个压入的数据:
MOV ESI,DWORD PTR DS:[EBX-4]
读第四个压入的数据:
MOV ESI,DWORD PTR DS:[EBS-0x10]
方式二:通过Top加偏移来读取
读第二个压入的数据:
MOV EDI,DWORD PTR DS:[EDX+4]
读第三个压入的数据:
MOV EDI,DWORD PTR DS:[EDX+8]
弹出数据
栈顶加4
方式一:
MOV ECX,DWORD PTR DS:[EDX]
LEA EDX,DWORD PTR DS:[EDX+4]
方式二:
MOV ESI,DWORD PTR DS:[EDX]
ADD EDX,4
方式三:
LEA EDX,DWORD PTR DS:[EDX+4]
MOV ESI,DWORD PTR DS:[EDX-4]
标志寄存器
31-12 | OF | DF | IF | TF | SF | ZF | 0 | AF | 0 | PF | 1 | CF |
---|---|---|---|---|---|---|---|---|---|---|---|---|
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
CF :进位标志(Carry Flag)
如果运算结果的最高位(先要知道数据宽度)产生了一个进位或借位,那么其值为1,否则为0
MOV AL.0xEF ADD AL,2
MOV AL,0xFF ADD AL,2
若算术产生的结果在最高有效位(most-significant bit)发生进位或者借位则将其置1 反之清零
这个标志通常用来指示无符号证书运算的溢出状态
宽度溢出位。只要容器内放不下就会发生变化
PF :奇偶标志(Padity Flag)
用于反映运算结果(最低有效字节位,最后一个字节)中“1”的个数的奇偶性,如果为偶数,则PF的值为1,否则为0
MOV AL,3
ADD AL,3
ADD AL,2
如果结果的最低有效字节 最后一个字节(least-significant byte)包含偶数个1位则该位置1,否则清零
利用PF可进行奇偶校验检查
需要传输1100 1110,数据中含5个1,所以其奇校验位位0,同时吧1100 1110传输给接收方,
接收方收到数据后再一次计算奇偶性,1100 1110中仍然含有5个1,所以接收方计算出的奇偶验位还是0,与发送方一致,表示在此次传输过程中未发生错误
AF:辅助进位标志(Auxiliary Carry Flag)
在发生下列情况时,AF为1,否则为0
1.在字操作时,发生低字节向高字节进位或借位时
2.在字节操作时,发生低4位向高4位进位或借位时
MOV EAX,0x55EEFFFF ADD EAX,2
MOV AX,5EFF ADD EAX,2
MOV AL,4E ADD AL,2
ZF:零标志(Zero Flag)用的最多
反映运算结果是否为0
如果运算结果为0,则ZF值为1,否则为0
XOR EAX,EAX
mov eax,2
sub eax,2
SF:符号标志(Sign Flag)
用来反映运算结果的符号位,它与运算结果的最高位相同
MOV AL,7L
ADD AL.2
OF:溢出标志(Overflow Flag)
用于反映有符号数加减运算所得的结果是否溢出
如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF值为1,否则为0
OF和CF区别
进位标志(CF)表示无符号数运算结果是否超出范围
溢出标志(OF)表示有符号数运算结果是否超出范围
溢出主要是给有符号运算使用的,有如下规律:
正+正=正 如果结果是负数,则说明有溢出
负+负=负 如果结果是正数,则说明有溢出
正+负 永远不会有溢出
1、无符号、有符号都不溢出
MOV AL,8
ADD AL,8
2、无符号溢出,有符号不溢出
MOV AL,0FF
ADD AL,2
3、无符号不溢出,有符号溢出
MOV AL,7F
ADD AL,2
4、无符号、有符号都溢出
MOV AL,0FE
ADD AL,80
DF[Diretion Flag]
这个方向标志控制字符串指令(MOVS
,CMPS,SCAS,LODS以及STOS
)。设置DF标志是的串指令自动递减(从高地址向低地址方向处理字符串),清楚该标志则是的串指令自动递增
STD以及CLD指令分别用户设置以及清除DF标志