文章目录
一、程序转换概述
二、IA-32指令集体系结构与常用指令操作
1.IA-32指令系统概述
IA-32是intel的32位指令集体系结构(IA32 ISA).
(1)数据类型
数据类型与长度利用汇编指令助记符后缀区分,以下为整数的IA-32操作数类型对照表:
C语言类型 | intel操作数类型与后缀 | 存储长度(位) |
---|---|---|
(unsigned)char | 字节/b | 8 |
(unsigned)short | 字/w | 16 |
(unsigned)int | 双字/l | 32 |
(unsigned)long int | 双字/l | 32 |
(2)寄存器
寄存器主要用来暂时存放运算中的数据,这里主要介绍定点寄存器.
[1] 8个通用寄存器: 主要用来存放操作数
作用 | 寄存器 | 31 ------ 16 | 15 -----7----- 0 |
---|---|---|---|
累加器寄存 | EAX | AH-(AX)-AL | |
基址寄存 | EBX | BH-(BX)-BL | |
计数寄存 | ECX | CH-(CX)-CL | |
数据寄存 | EDX | DH-(DX)-DL | |
栈指针 | ESP | SP | |
栈基址指针 | EBP | BP | |
源变址寄存器 | ESI | SI | |
目标变址寄存器 | EDI | DI |
[2] 2个专用寄存器(32位或16位):
-
指令指针寄存器EIP/IP: 与程序计数器PC功能一样,确定IA-32指令的执行顺序。
-
标志寄存器EFLAGS/FLAGS: 存放条件标志和控制标志。
条件标志:
条件标志 | 含义 | 说明 |
---|---|---|
OF | 溢出标志(带符号) | 高位相同且与结果不同则溢出,OF=1 |
SF | 符号标志(带符号) | 负数时,SF=1 |
ZF | 零标志 | 结果为0,ZF=1 |
CF | 进/借位标志(不带符号) | CF=SUB⊕C , 有进(借)位则CF=1 |
[3] 6个段寄存器(16位)
(3)寻址方式
寻址方式就是得到操作数或者操作数地址的方式.
-
立即寻址: $操作数
如$255, 表示直接给出操作数255. -
寄存器寻址: %寄存器名
如%eax, 表示操作数为R[eax]. -
存储器寻址: 偏移量(基址寄存器,变址寄存器,比例因子).
如100(%ebx,%esi,4), 表示M[ R[ebx] + 4*R[esi] +100 ],
2.IA-32常用指令
(1)传送指令
[1] 通用数据传送指令
- mov: 一般传送指令,包括movb,movw,movl.
- movs: 符号拓展传送指令,源数据高位符号拓展后传送.
- movz: 零拓展传送指令,源数据高位零拓展后传送.
- xchg: 数据交换指令,两个寄存器内容互换.
- push: 入栈指令,先更新栈指针寄存器保存的新地址,R[esp]<–R[esp]-4,再入栈:M[ R[esp] ]<–R[eax] (intel小端存储,入栈应入到低地址).
- pop: 出栈指令,先取得栈顶数据至指定寄存器,R[eax]<–M[ R[esp] ],再更新栈指针寄存器的值,R[sep]<–R[esp]+4.(这里表示32位的双字数据,16位单字数据用sp表示).
[2] 地址传送指令
- 格式: lea 存储器寻址操作数 , 非段寄存器寻址操作数.
- 意义:直接传送操作数的存储地址,即存储器操作数的地址.
[3] 输入输出指令:累加器与I/O端将数据传送(in,out).
[4] 标志传送指令:专门对标志寄存器操作.
(2)定点算术运算指令
[1] 加/减运算指令
- ADD/SUB:对两个位串进行相加或相减操作。(注意SUB是目的操作数-源操作数)
- 最多只能有一个存储器操作数 。
- 不区分无/带符号。
- 影响标志OF/CF/SF/ZF。
[2] 增/减运算指令
- INC/DEC:对一个位串加1或减1。
- 给定操作数既是源也是目的操作数。
- 不区分无/带符号。
- 影响标志OF/SF/ZF。
[3] 取负运算指令
- NEG:求一个操作数的负数,“各位取反,末位加一”。
- 给定操作数既是源也是目的操作数。
- 以字节操作数为例,若对-128取负,结果为-128且OF=1(溢出);若对0取负,结果为0且CF=0,否则总是CF=1。
[4] 比较运算指令
- CMP:对两个寄存器操作数比较,“目的操作数减去源操作数,但只改变标志位,两操作数保持原值”。
- 不区分无/带符号。
- 通常后面跟条件转移指令或条件设置指令。
[5] 乘/除运算指令
- 区分无/带符号,影响CF/OF。
乘运算指令:
- MUL/IMUL:无符号乘和带符号乘。
- 对于无符号乘MUL,只明显给出一个操作数SRC。
- 对于带符号乘IMUL,可明显给出一个、两个或三个操作数。
运算过程:
-
MUL/IMUL:只给出一个操作数SRC(存储器或者寄存器操作数),另一个源操作数在累加器AL/AX/EAX中,相乘结果存放在AX(AH-AL)/DX-AX/EDX-EAX中–>两个n位相乘,结果取2n位。
-
IMUL:给出两个操作数DST(寄存器操作数)、SRC(存储器或者寄存器操作数),结果存放在DST中–>两个n位相乘,结果取n位。
-
IMUL:给出三个操作数REG(寄存器操作数)、SRC(存储器或者寄存器操作数)、IMM(立即数),SRC和IMM相乘,结果存在REG中–>两个n位相乘,结果取n位。
标志位取值:
- 对于MUL指令:高n位全0则OF=CF=0,否则OF=CF=1。
- 对于IMUL指令:高n+1位全0(乘积正数)或全1(乘积负数)则OF=CF=0,否则OF=CF=1(CPU能处理截断前的2n位)。
除运算指令:
- DIV/IDIV:无符号除和带符号除
- 只明显给出除数,被除数在累加器AL/AX/EAX中,结果存放在AX(AH-AL)/DX-AX/EDX-EAX中,前余后商。
(3)按位运算指令
[1]逻辑运算指令
- NOT:但操作数取反。
- AND: 双操作数按位逻辑与,一般用来设置0,屏蔽特定位。
- OR:双操作数按位逻辑或,一般用来使特定位取1。
- XOR:双操作数按位逻辑异或,一般用来判断不同位或者改变特定位使其取反。
- TEST:双操作数按位逻辑与来设置条件标志,不改变原操作数,一般用来检测标志与判断。
- 标志位取值 :NOT不影响标志,OF=CF=0;当结果全0,ZF=1;当最高位为1,SF=1。
[2]移位指令
- SHL/SHR:逻辑移位,补0,高位或低位送入CF。
- SAL/SAR:算术移位,左移判溢出(符号位变化则OF=1),右移补符号。
- ROL/ROR:循环移位,低位移至高位或者高位移至低位,同时送入CF。
- RCL/RCR:带循环移位,将CF作为操作数的一部分循环移位。
(4)控制转移指令
IA-32中指令执行顺序由CS和EIP确定,可以改变CS和EIP或仅仅改变EIP来实现控制程序执行的转移
[1]无条件转移指令
- JMP DST:无条件转移到目标指令DST处执行。
[2]条件转移指令
- Jcc DST:cc为条件码,满足则转移到目标指令DST处执行,否则按顺序执行 。
- 以下为条件码cc的具体说明,如果满足cc对应的转移条件,则转移至label目标地址:
[3]条件设置指令
- SETcc DST:将条件码cc保存到DST(一般为8位寄存器),若满足条件cc,则DST寄存器内取1,否则取0.
[4]条件传送指令
- CMOVcc SRC,DST:cc为条件码,满足则传送操作,否则什么都不做。
- 源操作数SRC为16/32位寄存器或存储器操作数,而目的地DST必须为16/32位寄存器。
[5]调用和转移指令(用于过程调用)
跳转方式与JMP指令类似。
- CALL DST:是一种无条件转移指令,返回地址RA(CS:EIP/EIP寄存器的内容)入栈;将DST装入CS:EIP/EIP,跳转到DST处执行 。
- RET:也是一种无条件转移指令,从栈中取出返回地址RA送到CS:EIP/EIP寄存器,跳转到RA处执行。
[6]中断指令(具体在7、8章)
三、IA-32下 C语言程序的机器级表示
过程调用
(1)过程调用的步骤(过程P调用过程Q)
- P过程
- P将入口参数(实参)先右后左入栈。
- 执行CALL,保存返回地址,控制转移。
- Q过程
- 准备阶段1:保存P现场,初始化新EBP、ESP。
- 准备阶段2:分配局部变量
- 执行函数体
- 恢复P现场,释放局部变量。
- 取出返回地址,控制转移。
(2)相关操作:
-
保存旧EBP至当前栈帧底部并且设置EBP指向它
push %ebp
mov %esp ,%ebp -
取入口参数:
movl 16…
movl 12(%ebp) , %eax
movl 8(%ebp) , %edx -
EBP恢复旧值,ESP指向返回地址(即leave)
mov %ebp ,%esp
pop %ebp
选择语句
循环结构
原理同上