汇编基础
目录
一、通用寄存器
名字 用途 编号
32位 16位
EAX AX 累加器 000
ECX CX 计数 001
EDX DX I/O指针 010
EBX BX DS段的数据指针 011
ESP SP 堆栈指针 100
EBP BP SS段数据指针 101
ESI SI 字符串操作的源指针,ss段的数据指针 110
EDI DI 字符串操作目标指针;ES段的数据指针 111
32位专用寄存器EIP:保存当前下一条运行指针地址
2.段寄存器
代码段寄存器CS:存放当前正在运行的程序代码所在段的段基址
数据段寄存器DS:指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基址。
堆栈段寄存器SS:指出当前堆栈的底部地址,即存放堆栈段的段基址。
附加段寄存器ES:指出当前程序使用附加数据段的段基址,该段是串操作指令中目的串所在的段。
二、常用寻址方式
寻址方式就是寻找操作数或操作数地址的方式。
寄存器是中央处理器内的组成部分。寄存器是一组容量有限的高速存贮部件,它们可用来暂存指令、数据和位址。(DWORD)
MOV EAX,0x1234 //立即寻址
MOV EAX,EBX //寄存器寻址 数据寄存器,一般称之为通用寄存器组 通 用寄存器有4个 EAX,EBX,ECX,EDX
MOV EAX,[EBX] //寄存器间接寻址
MOV EAX,v //v是一个变量名
MOV EAX,[1234] //直接寻址方式
MOV EAX,[EBX+1234] //寄存器相对寻址
三、寻址公式
1. [立即数]
#内存读
mov eax,dword ptr ds:[0x19FF74]
#内存写
mov dword ptr ds:[0x19FF74],0xAABBCCDD
#获取内存编号
lea ecx,dword ptr ds:[0x19FF74]
2. [reg]
#内存读
mov ecx,0x19ff74
mov eax,dword ptr ds:[ecx]
#内存写
mov dword ptr ds:[ecx],0x87654321
#获取内存编号
lea eax,dword ptr ds:[ecx]
3. [reg+立即数]
#内存读
mov ecx,0x19ff74
mov eax,dword ptr ds:[ecx+4]
#内存写
mov dword ptr ds:[ecx+0xd],0x87654321
#获取内存编号
lea eax,dword ptr ds:[ecx+4]
- [reg+reg{1,2,4,8}]
注意,这里只能取1,2,3,4中的一个。
#内存读
mov ecx,0x19ff74
mov edx,2
mov eax,dword ptr ds:[ecx+edx*4]
#内存写
mov dword ptr ds:[ecx+edx*4],0x87654321
#获取内存编号
lea eax,dword ptr ds:[ecx+edx*4]
5. [reg+reg{1,2,4,8}+立即数]
#内存读
mov ecx,0x19ff74
mov edx,2
mov eax,dword ptr ds:[ecx+edx*4+4]
#内存写
mov dword ptr ds:[ecx+edx*4+4],0x87654321
#获取内存编号
lea eax,dword ptr ds:[ecx+edx*4+4]
四、堆栈操作
1.压入数据:
#模拟栈顶栈底
mov ebx,0x13ffdc #base
mov edx,0x13ffdc #top
#方式1
mov dword ptr ds:[edx-4],0xaaaaaaaa
sub edx,4
#方式2
sub edx,4
mov dword ptr ds:[edx],0xaaaaaaaa
#方式3
mov mov dword ptr ds:[edx-4],0xaaaaaaaa
lea edx,dword ptr ds:[edx-4]
#方式4
lea edx,dword ptr ds:[edx-4]
mov mov dword ptr ds:[edx],0xaaaaaaaa
2.读取数据:
#通过base加偏移读取第n个压入的数,n需指定
mov esi,dword ptr ds:[ebx-4*n]
#通过top加偏移读取
mov esi,dword ptr ds:[ebx+4*(n-1)]
3.弹出数据:
#方法1
mov ecx,dword ptr ds:[edx]
lea edx,dword ptr ds:[edx+4]
#方法2
mov esi,dword ptr ds:[edx]
add edx,4
#方法3
lea edx,dword ptr ds:[edx+4]
mov edi,dword ptr ds:[edx-4]
push指令:完成上述模拟的压入数据操作,ebx和esp分别为占地和栈顶,由cpu调配,随着压栈操作而自动变化,与容器宽度有关加减2或4。
push r32:esp-4
push r16:esp-2
push m16:esp-2
push m32:esp-4
push imm8/imm16/imm32:esp-4
pop指令:完成上述模拟的弹出数据操作,ebx和esp分别为占地和栈顶,由cpu调配,随着出栈操作而自动变化。
pop r32:esp+4
pop r16:esp+2
pop m16:esp+2
pop m32:esp+4
五、标志寄存器
- CF
进位标志(Carry Flag),如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。
MOV AX,0xFF00
ADD AX,0x0101
- PF
奇偶标志PF(Parity Flag):奇偶标志PF用于反映运算结果中最后一个字节中“1”的个数的奇偶性,如果“1”的个数为偶数,则PF的值为1,否则其值为0。
00010011 00010010
mov ax,0x1312
00010011 00010011 偶数 ,最后一字节为奇数-->p=0
add ax,1
00010011 00010100 奇数,最后一字节为偶数-->p=1
add ax,1
特别的,当最低有效字节为0时,PF=1
- AF
辅助进位标志(Auxiliary Carry Flag),在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:
在字操作时,发生低字节向高字节进位或借位时;
在字节操作时,发生低4位向高4位进位或借位时。
MOV AX,0x100f
ADD AX,0x4
- ZF
零标志(Zero Flag):零标志ZF用来反映运算结果是否为0,如果运算结果为0,则其值为1,否则其值为0。
- SF
符号标志(Sign Flag):符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。
mov al,0x82
add al,1
- OF
溢出标志(Overflow Flag):溢出标志OF用于反映有符号数加减运算所得结果是否溢;如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
最高位进位与溢出的区别:
进位标志表示无符号数运算结果是否超出范围.
溢出标志表示有符号数运算结果是否超出范围.
是否溢出的判别规律:
正 + 正 = 正 如果结果是负数,则说明有溢出
负 + 负 = 负 如果结果是正数,则说明有溢出
正 + 负 永远都不会有溢出.
- DF
方向标志位,默认从右操作数到左操作数,可以通过CLD和STD指令修改DF的值。
清方向位指令CLD(Clear Direction Flag):DF←0
置方向位指令STD(Set Direction Flag):DF←1
六、相关指令
1、ADC
带进位加法(C位参与运算),两边不能同时为内存,且数据宽度要一致。
格式:ADC R/M,R/M/IMM
ADC AL,CL
ADC BYTE PTR DS:[19ff74],2
ADC BYTE PTR DS:[19ff74],AL
2、SBB
带借位减法(C位参与运算),两边不能同时为内存,且数据宽度要一致。
格式:SBB R/M,R/M
SBB AL,CL
SBB BYTE PTR DS:[19ff74],2
SBB BYTE PTR DS:[19ff74],AL
- XCHG
交换数据,两边不能同时为内存,且数据宽度要一致。
格式:XCHG R/M,R/M
XCHG AL,CL
XCHG DWORD PTR DS:[19ff74],EAX
XCHG BYTE PTR DS:[19ff74],AL
4、MOVS
移动数据,把ESI存储的内存地址中的数据复制到EDI存储的内存地址中,每复制一次,两个操作数均向上或下偏移4/2/1个字节(地址递增或递减,便于复制下一串内容),当D=0时递增,D=1时递减。
格式:
MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI],简写为movsb
MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI],简写为MOVSW
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI],简写为movsd
5、STOS
将AL/AX/EAX的值存储到[EDI]指定的内存单元,D=0时地址递增,D=1时地址递减。
格式:
STOS BYTE PTR ES:[EDI],简写为STOSB
STOS WORD PTR ES:[EDI],简写为STOSW
STOS DWORD PTR ES:[EDI],简写为STOSD
6、REP
按计数寄存器 (ECX) 中指定的次数重复执行字符串指令。
7、JCC
比较指令
- Cmp
格式:CMP R/M,R/M/IMM
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结果并不保存到第一个操作数中;只是根据相减的结果来改变零标志位的(其他标志位也可以更改),当两个操作数相等的时候,零标志位置1。
9、test
指令格式:TEST R/M,R/M/IMM
该指令在一定程序上和CMP指令时类似的,两个数值进行与操作,结果不保存,但是会改变相应标志位;用这个指令,可以确定某寄存器是否等于0。
10、jmp
无条件转移指令,仅可以修改EIP的值,相当于mov eip,立即数/寄存器。
格式:jmp 寄存器/立即数
11、call
call指令用于调用子程序,先将当前的EIP压栈保存,然后jmp 目标地址,相当于:
PUSH eip
mov eip,地址A/寄存器
格式:call 地址A/寄存器
12、ret
ret指令用于回到程序调用点,与call配套使用,先将eip出栈,然后jmp eip,相当于:
lea esp,[esp+4]
mov eip,[esp-4]