汇编辅助基础理论(二)

【汇编辅助基础理论(二)】标志寄存器EFLAGS一共有32位 , 在这32位中大部分是保留和给编写操作系统的人用的 , 一般情况下只需知道32位的第16位中的8位即可 , 图1-3列出了标志寄存器EFLAGS中需要了解的8个位的位置 。
*OF(OverflowFlag):溢出标志 , 溢出时为1 , 否则置0 。
DF(DirectionFlag):方向标志 , 在串处理指令中控制信息的方向 。
IF(InterruptFlag):中断标志
AF(AuxiliarycarryFlag):辅助进位标志 , 有进位时置1 , 否则置0 。
ZF(ZeroFlag):零标志 , 运算结构为0时ZF位位置1 , 否则置0 。
SF(SignFlag):符号标志 , 结果为负时置1 , 否则置0 。
CF(CarryFlag):进位标志 , 进位时置1 , 否则置0 。
PF(ParityFlag):奇偶标志 。 结果操作数中1的个数为偶数是置1 , 否则置0
(1)立即寻址
示例:
Moveax,[12558878H]
作用:通常用于处理变量 。
(2)直接寻址
示例:
Moveax,[12558878H]
作用:通常用于处理变量 。
一般高级语言中的数据结构和寻址方式有一定的关系 , 熟悉这些关系对逆向分析反汇编指令有很大的帮助 。 表1-1所示为高级语言中的数据结构和80386寻址方式的关系 。
80386指令
观察一下Intel的80x86CPU文档手册会发现 , Intel的80x86CPU支持几百条指令 , 如此多的指令莫说深入研究 , 连入门恐怕也非易事 。
幸运的是 , 在这几百条的指令中 , 常用的也不过几十条而已 , Intel的80x86CPU之所以支持几百条指令 , 原因在于Intel的80x86CPU为了保持向下兼容的问题 , 所以从过去到现在的所有指令都包含在CPU里面 , 例如有8086/8088、80186、80286和80386等 。
Intel格式和AT&T格式(&在英语里读and)
编写IA-32架构的汇编语言常见有两种格式 , 一种是Intel格式 , 另一种是AT&T格式 。
(1)Intel格式的指令格式 。
指令名称目标操作数DST , 源操作数SRC
示例代码:
Moveax,[edx]//将内存地址为EDX的数据放入EAX寄存器
Xchgeax,edi//交换EAX和EDI寄存器的值
Addeax,ebx//将EAX和EBX相加 , 结构放回EAX中
Shleax,4//将EAX逻辑左移4位 。
(2)AT&T格式的指令格式 。
指令名称源操作数SRC , 目标操作数DST
示例代码:
Mov(%EDX),%EAX//将内存地址为EDX的数据放入EAX寄存器
XCHG%EDI,%EAX//交换EAX和EDI寄存器的值
ADD%EBX,%EAX//将EAX和EBX相加 , 结构放回EAX中
SHL$4,%EAX//将EAX逻辑左移4位 。
本教程中讲解的汇编语言统一采用Intel格式的汇编格式 。
下节课介绍在实际中的80386汇编语言常见指令集 。
80386的数据传送指令是为了实现CPU和内存、输入/输出端口之间的数据传送 。
(1)MOV:称为数值传送指令 , 格式是“MOVDST,SRC” 。
(2)MOV指令将源操作数SRC传送到目的操作数DST中 ,
(3)传送的数据格式可以是8字节、16字节和32字节 。
示例代码:
MOVEAX,56//将56H立即数传送到EAX寄存器
MOVESI,DWRODPTR[EAX*2+1]//将内存地址为EAX*2+1处的4字节数据传送到ESI寄存器 。
MOVAH,BYTEPTR[ESI*2+EAX]//将内存地址为ESI*2+EAX处的8位数据传送到AH寄存器 。
MOVDWORDPTR[ESP+36],EBX//将EBX寄存器的值以4字节传送到堆栈地址为ESP+36所指向的地方 。
(4)XCHG:称为交换指令 , XCHG实现寄存器间和内存间的数据交换 。
格式是“XCHGDST,SRC” 。 XCHG指令交换SRC和DST之间的数据 ,
交换的数据可以是8字节、16字节和32字节 , 其中SRC和DST必须格式相同 。
示例代码:
XCHGEAX,EDX//将EDX寄存器的值和EAX寄存器的值交换
XCHG[ESP-55],EDI//将EDI寄存器的值和堆栈地址为[esp-55]处的值交换 。
XCHGBH,BL//将BL寄存器和BH寄存器的值交换 。
PUSH和POP:称为压入堆栈指令和弹出堆栈指令 , 格式是“PUSHSRC(源操作数)”和“POPDST(目的操作数)” 。
PUSH指令和POP指令是匹配出现的 , 上面的代码有多少个PUSH下面的代码就有多少个POP , 否则堆栈就会不平衡 。
PUSH指令将源操作数SRC压入堆栈 , 同时ESP-4 , 而POP恰恰相反 , POP指令从堆栈的顶部弹出4字节的数值然后放入DST 。 在32位的Windows操作系统上 , PUSH和POP指令的操作是以4字节为单位的 。
PUSH和POP指令常用于向函数传递参数 。 huibian
示例代码:
PUSHEAX//将EAX寄存器的值以4字节压入堆栈 , 同时ESP-4
PUSHDWORDPTR[12FF8589]//将内存地址为12FF8589所指向的值以4字节压入堆栈 , 同时ESP-4
-------------------------
POPDWORDPTR[12FF8589]//将堆栈顶部的4字节弹出到内存地址为12FF8589所指地方 , 同时ESP+4
POPEAX//将堆栈顶部的4字节弹出到EAX寄存器 , 同时ESP+4
80x86有3条地址传送指令 , 分别是LEA , LDS和LES 。 其实LDS和LES指令和段寄存器有关 , 在32位的Windows操作系统上 , 一般的程序员都不需要管理段寄存器 , 所以相对而言 , LDS和LES寄存器使用得比较少 , 一般情况下常见的只有LEA指令 。
LEA:称为地址传送指令 , 格式是“LEADST,ADDR” 。 LEA指令将ADDR地址加载到DST , 其中ADDR可以是内存 , 也可以是寄存器 , 而DST必须是一个通用寄存器 。
LEA指令相当于C语言中的“&”and操作符 , 需要注意的是LEA和MOV是不同的 , 前者传送的是地址 , 后者传送的是操作数 。
示例代码:
LEAEAX,[12345678]
MOVEAX,[12345678]
//指令执行后EAX寄存器的值为12345678H , 而MOVEAX,[12345678]指令执行后EAX寄存器的值为内存地址12345678指向的那个数值 。
还有一点需要注意LEA指令可用于算法运算 。
示例代码:
LEAECX,[ECX+EAX*4]//ECX=ECX+EAX*4


    推荐阅读