16位和32位的80x86之间的区别
- 16位操作系统中的中断调用相当于32位操作系统中的API调用。16位操作系统中的段地址和偏移地址在32位中消失了,
在32位操作系统中统一采用平坦的内存地址模式寻址
- 16位操作系统中的程序运行在RING0级,也就是说普通程序和操作系统程序运行在同一个级别并且拥有最高权限,而
32位操作系统中的程序一般只拥有RING3级运行权限,程序的所有操作都受到操作系统控制,若程序要获得RING0操作特权只能通过驱动程序实现
- 16位操作系统的可执行文件格式和32位操作系统的可执行文件格式不同,
在32位的Windows操作系统中,可执行文件的格式叫PE格式,32位的Windows操作系统运行在CPU的保护模式之上
,而16位的系统则运行在CPU的实模式上
通用寄存器
IA-32架构中一共有4个32位寄存器,用于保存临时数据,
这4个通用寄存器
可以当作16位使用,也可以当作8位使用.它们的用途不是一成不变的,编译器在编译程序的时候会根据很多因素,例如编译器、编译条件、操作系统等做出相应的改变
EAX
EAX称为累加器,常用于算数运算、布尔操作、逻辑操作、返回函数结果等
EBX
EBX称为基址寄存器,常用于存档内存地址
ECX
ECX称为计数寄存器,常用于存放循环语句的循环次数,字符串操作中也常用
EDX
EDX称为数据寄存器,常常和EAX一起使用
变址寄存器
变址寄存器存放在变动的内存地址
ESI
ESI称为源变址寄存器,通常存放
要处理的数据
的内存地址
EDI
EDI称为目的变址寄存器,通常存放
处理后的数据
的内存地址
ESI和EDI常用来配合使用完成数据的赋值操作。
Rep movs dword ptr[edi],dword ptr[esi]
把ESI所指向的内存地址中的内容复制到EDI所指向的内存中,数据长度在ECX中指定
指针寄存器
EBP
EBP称为基址寄存器,可作为通用寄存器用于存放操作数,常用来代替堆栈指针访问堆栈的数据
ESP
ESP称为堆栈指针寄存器,不可作为通用寄存器使用,ESP存放当前堆栈栈顶的地址,一般情况下,ESP和EBP联合使用来访问函数中的参数和局部变量
EIP
指令指针寄存器EIP总是指向下一条要执行的指令的地址.
常见的访问堆栈指令:
push ebp
mov ebp,esp
sub esp,78
push esi
push edi
cmp dword ptr [ebp+8],0
标志寄存器
标志寄存器EFLAGS一共有32位,在这32位中大部分是保留给编写操作系统的人用的
- OF(Overflow Flag):溢出标志,溢出时为1,否则置0。
- DF (Direction Flag):方向标志,在串处理指令中控制信息的方向。
- IF (Interrupt Flag) :中断标志
- AF (Auxiliary carry Flag) :辅助进位标志,有进位时置1,否则置0。
- ZF (Zero Flag) :零标志,运算结构为0时ZF位位置1,否则置0。
- SF (Sign Flag):符号标志,结果为负时置1,否则置0。
- CF (Carry Flag): 进位标志,进位时置1,否则置0。
- PF (Parity Flag): 奇偶标志。结果操作数中1的个数为偶数时置1,否则置0。
EFLAGS是实现条件判断和逻辑判断的一种机制
,在汇编语言中一般不直接访问EFLAGS寄存器,而是通过指令的操作隐含访问
EFLAGS寄存器
Cmp dword ptr [ebp+8],0 //影响标志CF、ZF、SF、OF、AF和PF
Jz 00405898 //如果ZF等于1,则跳转到00405898
x86指令
数据传送指令
数据传送指令是为了实现CPU和内存、输入/输出端口之间的数据传送
MOV
mov eax,56 // 将56H传送到eax寄存器
mov esi,dwrod ptr [eax*2+1] // 将内存地址为eax*2+1处的4字节数据传送到esi寄存器
mov ah,byte ptr [esi*2+eax] // 将内存地址为esi*2+eax处的8位数据传送到AH寄存器
XCHG
寄存器和内存的数据交换,交换的数据可以是8字节、16字节和32字节,必须格式相同
xchg eax,edx // 将edx寄存器的值和eax寄存器的值交换
xchg [esp-55],edi // 将edi寄存器的值和堆栈地址为[esp-55]处的值交换
PUSH POP
PUSH和POP:称为压入堆栈指令和弹出堆栈指令,格式是“PUSH SRC(源操作数)”和“POP DST(目的操作数)”。
PUSH指令和POP指令是匹配出现的,上面的代码有多少个PUSH下面的代码就有多少个POP,否则堆栈就会不平衡。
PUSH指令将源操作数SRC压入堆栈,同时ESP-4,而POP恰恰相反,POP指令从堆栈的顶部弹出4字节的数值然后放入DST。在32位的Windows操作系统上,PUSH和POP指令的操作是以4字节为单位的。
PUSH和POP指令常用于向函数传递参数
push eax //将EAX寄存器的值以4字节压入堆栈,同时ESP-4
push dwrod ptr [12FF8589] //将内存地址为12FF8589所指向的值以4字节压入堆栈,同时ESP-4
-------------------------
pop dwrod ptr [12FF8589] //将堆栈顶部的4字节弹出到内存地址为12FF8589所指地方,同时ESP+4
pop eax //将堆栈顶部的4字节弹出到EAX寄存器,同时ESP+4
地址传送指令
x86有3条地址传送指令,分别是LEA,LDS和LES。其实LDS和LES指令和段寄存器有关,在32位的Windows操作系统上,一般的程序员都不需要管理段寄存器,所以相对而言,LDS和LES寄存器使用得比较少,一般情况下常见的只有LEA指令。
LEA
称为地址传送指令,格式是“LEA DST,ADDR”。LEA指令将ADDR地址加载到DST,其中ADDR可以是内存,也可以是寄存器,而DST必须是一个通用寄存器
lea eax,[12345678]
mov eax,[12345678]
//指令执行后EAX寄存器的值为12345678H,而MOV EAX,[12345678] 指令执行后EAX寄存器的值为内存地址12345678指向的那个数值。
//LEA指令可用于算法运算。
lea ecx,[ecx+eax*4] //ECX=ECX+EAX*4
算数运算指令
80x86提供了8条加减法指令:ADD、ADC、SUB、SBB、INC、DEC、CMP和NEG,4条乘除法指令:MUL、IMUL、DIV和IDIV
ADD
称为加法指令
add eax,esi //将EAX寄存器的值加上ESI寄存器的值,得出的结果保存在EAX的寄存器中
add ebx,dwrod ptr[12345678] //将EBX寄存器的值加上内存地址为12345678所值的4字节值,得出的结果保存在EBX寄存器中.
// 不同的平台和编译器中,DWROD占用的字节数不同,在32位的window中一个WROD占用16字节空间,DWORD占用32字节空间
SUB
称为减法指令
sub ecx,4H //将ECX寄存器的值减去4H,得出的结果保存在EAX寄存器中。
sub byte ptr[eax],ch //将内存地址为EAX所指向的数据按字节为单位和CH寄存器相减,得出的结果按字节为单位保存在EAX所指向的地方。
INC
称为加1指令
inc eax //将EAX寄存器的值加1,得出的结果存放在原来的地方
DEC
称为减1指令
dec edx //将DEC寄存器的值减1,得出的结果存放在原来的地方
CMP
称为比较指令格式是“CMP OPER1,OPER2”.
CMP指令将OPER1减去OPER2,得出的结果不保存,只是相应地设置寄存器EFLAGS的CF、PF、ZF、AF、SF和OF。也就是说可以通过测试寄存器EFLAGS相关的标志的值得知CMP指令执行后的结果
CMP EAX,56H //将EAX寄存器的值减去56H,得出的结果不保存,并且设置寄存器EFLAGS相关的标志位
NEG
NEG:称为取补指令,格式是“NEG OPER”。
NEG指令将OPER操作数取反,简而言之就是将零减去OPER操作数,得出的结果保存在OPER自身中。
在计算机的CPU中没有减法的机制,减法是用加法实现的,例如:100-55这个操作,CPU实际执行的是100+(-55),而-55相当于是求55的相反数,求相反数的时候NEG指令正好派上用场了
NEG EAX //将EAX寄存器的值取反,得出的结果保存在EAX中
MUL IMUL
称为无符号乘法指令,格式是“MUL OPER”。
MUL指令隐含了一个参加运算的操作数EAX寄存器,MUL指令将EAX寄存器的值乘以OPER,得出的结果保存在EAX寄存器中。如果结果超过32位,则高32位使用EDX寄存器保存,EAX寄存器则保存低32位
MUL EDX //将EAX寄存器的值乘以EDX寄存器的值,得出的结果保存在EAX寄存器中。
IMUL称为有符号乘法指令,原理和操作可以参考MUL指令,IMUL和MUL的区别是IMUL将参与运算的操作数当成有符号数来处理。
DIV IDIV
DIV:称为除法指令,格式是“DIV OPER”。
DIV 指令将64位(EDX和EAX)或32位(EAX)的值除以OPER,得出的商保存在EAX寄存器中,而余数则保存在EDX寄存器中,由OPER操作数决定按多少字节操作。
DIV ECX //将EAX寄存器的值按4字节为单位除以ECX寄存器的值,得出的结果商保存在EAX寄存器中,余数保存在EDX寄存器中。
DIV WORD PTR [ESP+36] //将EAX寄存器的值按WORD为单位除以堆栈地址为ESP+36所指向的数据,得出的结果商保存在EAX寄存器中,余数保存在EDX寄存器中。
IDIV:称为有符号除法指令,原理和操作可以参考DIV指令,IDIV和DIV的区别是IDIV将参与运算的操作数当成有符号数来处理。
高级语言中的数据结构和80386寻址方式的关系
- CS(Code Segment):代码段寄存器;
- DS(Data Segment):数据段寄存器;
- SS(Stack Segment):堆栈段寄存器;
- ES(Extra Segment):附加度段寄存器
6种灵活的寻址方式与其作用
说明 | 示例 | 作用 |
---|---|---|
立即寻址 | mov eax,56H | 通常用于赋值 |
直接寻址 | mov eax,[1255887H] | 通常用于处理变量 |
寄存器寻址 | mov eax,[edi] | 地址在寄存器中 |
寄存器相对寻址 | mov eax,[edi+20H] | 常用于访问数组和结构 |
基址加变址寻址 | mov eax,[EBP+ESI] | 常用于访问数组 |
相对基址加变址寻址 | mov eax,[EBX+EDI-10H] | 常用于访问结构 |