简介
熟悉IA-32处理器通用的基本指令
- 数据传送指令
- 算术运算指令
- 逻辑运算指令
- 移位操作指令
掌握指令功能和编程应用
学习指令的注意事项
指令的功能
- 指令能够实现何种操作
- 指令助记符是指令功能的英文单词或其缩写形式
指令支持的寻址方式
- 指令中的操作数可以采用何种寻址方式
指令对标志的影响
- 指令执行后是否对各个标志位有影响,以及如何影响
其他方面
- 指令执行时的约定设置
- 必须预置的参数
- 隐含使用的寄存器
80x86指令系统
80x86高档微处理器包含如下指令系统
- 通用指令集(CPU)
- 浮点指令集(FPU浮点处理器)
- MMX指令集(多媒体扩展指令集)
- SSE和SSE2指令集(流式单指令多数据扩展指令集)
指令系统
计算机所能执行的各种代码指令的集合
80x86cpu的通用指令分为6大类
- 数据传送指令
- 算术运算指令
- 逻辑运算指令
- 字符串处理指令
- 控制与转移指令
- 处理机控制指令
1.数据传送类指令
数据传送
- 把数据从一个位置传送到另一个位置
- 计算机中最基本的操作
- 程序设计中最常使用的指令
- 除标志寄存器传送指令外,均不影响标志位
全面而准确地理解每条指令的功能和应用 是编写汇编语言程序的关键 也是理解处理器如何进行数据处理的核心
数据传送类指令
数据传送指令
- MOV (MOVe ) 传送
- MOVSX(MOVe with Sign-eXtend)
- MOVZX(MOVe with Zero-eXtend)
- XCHG互换指令
堆栈操作指令
- PUSH 入栈 – POP 出栈
地址传送指令
- LEA(Load effictive Address)装入有效地址
换码指令
- XLAT 换码
标志传送指令
- LAHF(Load AH with Flags) 标志寄存器低8位传送AH
- SAHF(Store AH into Flags) AH寄存器传送到标记寄存器低8位
1.1 通用数据传送指令
提供方便灵活的通用数据传送操作
主要有传送MOV和交换XCHG指令
1.传送指令MOV
把一个字节、字或双字的操作数从源位置传送至目的位置
MOV指令限制的情况
源操作数和目的操作数
- 数据类型必须一致
- 不能同时使用存储器寻址方式
目的操作数
- 不可以是:立即数,EIP,IP和CS
段寄存器
- 不能相互传送
- 立即数不能直接传送
部分限制的解决
MOVZX 带0(零位)扩展传送指令
适用于无符号整数,标志位无变化。
源操作数中的数据复制到目的操作数,并将0扩展到16bit(32bit)
MOVSX 带符号扩展传送指令
源操作数中的数据复制到目的操作数,将符号位扩展到16bit或32bit.
2.交换指令XCHG
将源操作数和目的操作数内容交换
XCHG reg,reg
XCHG reg,mem
XCHG mem,reg
- 通用寄存器与通用寄存器之间
- 通用寄存器与存储器之间
//交换
mov ax,val1
xchg ax,val2
mov val1,ax
空操作指令NOP(XCHG EAX,EAX)
- 操作码 90H
- 实现短时间延时
- 临时占用代码空间
1.2 堆栈及操作
特殊的内存区,暂时存放数据和地址
操作方式:后进先出(LIFO)/先进后出 (FILO)
处理器用硬件支持堆栈数据结构
堆栈指针ESP
- 随有关指令自动增减
- 属于专用寄存器
- 有通用寄存器灵活应用特点
可赋值: sub esp,4 mov esp,ebp
可寻址: mov ebx,[esp+4]
IA-32处理器堆栈操作
入栈和出栈指令
Push reg16 POP reg16
Push mem16 POP mem16
Push seg POP reg32
Push reg32 POP mem32
Push mem32
Push imm32
ESP操作规则:
- 字为2,双为4
- 入先-,出后+
push操作示意图
pop操作示意图
Pushfd与Popfd
- Pushfd将EFLAGS寄存器 内容压入堆栈
- Popfd将栈顶单元内容弹 出到EFLAGS
- EFLAGS寄存器为标记寄存器
通用寄存器入栈、出栈
Pushad - EAX,ECX,EDX,EBX,ESP,EBP,E SI,EDI顺序将32位寄存器压 栈
Pusha
- AX,CX,DX,BX,SP,BP,SI,DI顺 序将16位寄存器压栈
堆栈不平衡问题
堆栈的应用
使用堆栈的指令
- 堆栈操作类指令,例如PUSH,POP
- 过程调用CALL和返回RET
堆栈的应用
- 临时存放寄存器数据,以便随时恢复
- 执行CALL时,保存当前过程的返回地址
- 调用程序与过程间传递参数,例如C/C++的函数调用
- 过程内局部变量的临时存储区
要点: - 保持堆栈平衡,例如入栈和出栈成对使用
字符串反转
1.3 地址传送指令
获取存储器操作数的偏移地址
- LEA r16/r32,mem
类似于地址操作符OFFSET的作用
- LEA指令在指令执行时计算出偏移地址,运行时
- OFFSET操作符在汇编阶段取得变量的偏移地址,编译时
优缺点
- OFFSET无需在执行时计算、指令执行速度更快
- LEA指令能获取汇编阶段无法确定的偏移地址
lea esi, var
mov edi, offset var
地址传送程序
;数据段
dvar dword 41424344h
;代码段
mov eax,dvar
lea esi,dvar
mov ebx,[esi]
mov edi,offset dvar
mov ecx,[edi]
lea edx,[esi+edi*4+100h]
1.4 换码指令
XLAT指令功能:AL←[EBX+AL]
- 将EBX指定的缓冲区中
- AL指定的位移处的一个字节数据
- 取出赋给AL
换码指令执行前:
- 在主存建立一个字节量表格,内含要目的代码
- 表格首地址存放于EBX
- AL存放相对表格首地址的位移量
换码指令执行后:
- 将AL寄存器的内容转换为目标代码
1.5 标志传送指令LAHF,SAHF
LAHF将EFLAGS的低字节复制到AH寄存器
SAHF将AH寄存器的内容复制到EFLAGS的低字节
影响的标志位:SF、ZF、AF、PF、CF标志
标志位操作符
- CLC 清除CF位(CF=0) STC 设置CF位(CF=1) CMC取反CF位
应用举例
.data
saveflags byte ?
.code
lahf
mov saveflags,ah
......
mov ah,saveflags
sahf
2.算术运算类指令
算术运算
- 对数据进行加减乘除
- 基本的数据处理方法
- 加减运算的进位、借位、溢出状态也是结果的一部分
关注对标志的影响
- 掌握:加法和减法指令
- 熟悉:乘法和除法指令
- 理解:零位扩展和符号扩展
2.1 状态标志
状态标志是处理器最基本的标志
用途
- 作为加减运算和逻辑运算的辅助结果
- 构成各种条件,实现程序分支
进位标志CF(Carry Flag)
CF=1
- 加减运算结果的最高 有效位有进位(加法) 或借位(减法)时
用途
- 判断无符号整数加减 结果是否超出表达范 围
如何改变CF值?
- STC 置位CF = 1
- CLC 清位CF = 0
- CMC 变反CF位
溢出标志OF(Overflow Flag)
OF=1 - 有符号数加减结果有溢出
用途
- 判断有符号整数加减结果是否超出表达范围
处理器硬件判断规则
- 最高位和次高位同时有进位或同时无进位,无溢出
- 最高位和次高位进位状态不同,有溢出
人工判断
- 当两个相同符号数相加(两个不同符号数相减),而运算结果 的符号与原数据符号相反时,产生溢出
进位和溢出的区别
CF反映无符号整数运算结果是否超出范围
- 有进位,加上进位或借位后运算结果仍然正确
OF反映有符号整数运算结果是否超出范围
- 有溢出,运算结果已经不正确
处理器按照无符号整数求得结果
- 设置进位标志CF
- 设置溢出标志OF
程序员决定
- 操作数是无符号数,关心进位CF
- 操作数是有符号数,注意溢出OF
零标志ZF(Zero Flag)
运算结果为0,则ZF=1,否则ZF=0
结果是0, ZF标志不是0 !
符号标志SF(Sign Flag)
运算结果最高位为1,则SF=1;否则SF=0
最高位=符号位=SF
奇偶标志PF(Parity Flag)
当运算结果最低字节中“1”的个数为零或偶数时, PF=1;否则PF=0 (仅最低8位“1”的个数)
2.2 加法指令
加法指令 ADD
带进位加法指令 ADC
增量指令 INC
- INC不影响CF,影响其他标志位
- ADD,ADC按定义设置全部状态标志位
数据传送类指令不影响(=不改变)状态标志
加法和减法指令根据结果按定义改变状态标志
1. 加法指令ADD
目的操作数加源操作数,和送到目的操作数
- ADD reg,imm/reg/mem ;reg←reg+imm/reg/mem
- ADD mem,imm/reg ;mem←mem+imm/reg
按照定义影响6个状态标志位(CF,OF,SF,ZF,AF,PF)
- mov eax,0aaff7348h ;EAX=AAFF7348H
- add al,27h
- add ax,3fffh
- add eax,88000000h
2. 带进位加法指令ADC
两个操作数相加,再加CF,结果送目的操作数
- ADC reg,imm/reg/mem ;reg←reg+imm/reg/mem+CF
- ADC mem,imm/reg ;mem←mem+imm/reg+CF
用于与ADD指令相结合实现多精度数的加法
- 先将两个操作数的低32位相加(用ADD指令)
- 再加高位部分、并将进位加到高位(用ADC指令)
64位数据相加程序
mov eax,dword ptr qvar1 ;取低32位
add eax,dword ptr qvar2 ;加低32位,设置CF
mov edx,dword ptr qvar1+4 ;取高32位
adc edx,dword ptr qvar2+4 ;加高32位,同时加CF
3. 增量指令INC
对操作数加1(增量)再将结果返回原处
- INC reg/mem ;加1:reg/mem←reg/mem+1
用于计数器和地址指针的调整
不影响进位CF标志,影响其他状态标志位
例
inc ecx
inc dword ptr [ebx]
inc wvar
2.3 减法指令
减法指令 SUB
带借位减法指令 SBB
减量指令 DEC
求补指令 NEG
比较指令 CMP
- 除DEC不影响CF标志外
- 其他按定义影响全部状态标志位
1. 减法指令SUB
目的操作数减源操作数,差送到目的操作数
- SUB reg,imm/reg/mem ;reg←reg-imm/reg/mem
- SUB mem,imm/reg ;mem←mem-imm/reg
按照定义影响6个状态标志位
mov eax,0aaff7348h ;EAX=AAFF7348H
sub al,27h
sub ax,3fffh
sub eax,0bb000000h
2. 带借位减法指令SBB
目的操作数减源操作数,再减CF,结果送目的操作数
- SBB reg,imm/reg/mem ;reg←reg-imm/reg/mem-CF
- SBB mem,imm/reg ;mem←mem-imm/reg-CF
用于与SUB指令相结合实现多精度数的减法
- 先将两个操作数的低32位相减(用SUB指令)
- 然后减高位部分、并减去借位(用SBB指令)
3. 减量指令DEC
只有一个操作数:寄存器或存储单元
对操作数减1(减量)再将结果返回原处 - DEC reg/mem ;减1:reg/mem←reg/mem-1
用于计数器和地址指针的调整
不影响进位CF标志,影响其他状态标志位
例如
dec cx
dec byte ptr [ebx]
dec wvar
4. 求补指令NEG
对操作数执行求补运算,即用零减去操作数
- NEG reg/mem ;reg/mem←0-reg/mem
对标志的影响与用零作减法的SUB指令一样
可用于对负数求补码或由补码求其绝对值
mov ax,0ff64h
neg al
sub al,9dh
neg ax
dec al
neg ax
5. 比较指令CMP
将目的操作数减去源操作数,差值不回送目的操作数
按照减法结果影响状态标志
- CMP reg,imm/reg/mem ;reg-imm/reg/mem
- CMP mem,imm/reg ;mem-imm/reg
根据标志状态获知两个操作数的大小关系
给条件转移等指令使用其形成的状态标志
2.4 乘法和除法指令
IA-32处理器针对无符号数和有符号数采用不同的 乘法和除法指令
有符号数指令前用I(sIgned)表示
隐含使用EAX(和EDX)寄存器
255的机器表示FF
-1的机器表示FF
-1×-1 = 1
FF×FF = 1 ?
1. 乘法指令
无符号数:mul src
有符号数: imul src
指令类型 | 操作数组合及功能 | 举例 |
---|---|---|
无符号数乘法 有符号乘法 | AX = AL * r8 / m8 DX.AX = AX * r16 / m16 EDX.EAX = EAX * r32 / m32 | mul bl imul bx mul exb |
双操作数乘法 IMUL dest, src | r16 = r16 * r16 / m16 / i8 / i16 r32 = r32 * r32 / m32 / i8 / i32 | imul eax, 10 imul ebx ,ecx |
三操作数乘法 IMUL dest, src, imm | r16 = r16/m16 * i8 / i16 r32 = r32 / m32 * i8 / i32 | imul ax, bx ,-2 |
imul eax,dword ptr [esi+8],5
2.除法指令
无符号:div
有符号:idiv
div指令除法溢出
- 除数为0
- 字节除时商超过8位
- 字除时商超过16位
- 双字除时超过32位
idiv指令除法溢出
- 除数为0
- 字节除时商不在-128~127范围内
- 字除时商不在-32768~32767范围内
- 双字除时商不在-231~231-1范围内
除法错溢出产生0号内部中断
除法指令
指令 | 操作数组合及功能 | 举例 |
---|---|---|
无符号除法: div src | AL < ---- AX / r8/m8 的商 AH < ---- AX / r8/m8 的余数 AX < ---- DX.AX / r16/m16 的商 | div bl div ebx |
有符号除法: idiv src | AX < ---- DX.AX / r16/m16 的余数 EAX < ---- EDX.EAX / r32/m32 的商 EAX < ---- EDX.EAX / r32/m32 的余数 | idiv ebx |
2.5 符号扩展指令
CBW
- 将AL中数据符号扩展到AX中
CWD
- 将AX中数据符号扩展到DX和AX中
CWDE
- 将AX中数据符号扩展到EAX中
CDQ
- 将EAX中数据符号扩展到EDX和EAX中
十进制调整指令
压缩BCD码调整指令
- DAA 十进制加法调整
- DAS 十进制减法调整
非压缩BCD码调整指令
- AAA ASCII码加法调整
- AAS ASCII码减法调整
- AAM ASCII码乘法调整
- AAD ASCII码除法调整
3.位操作类指令
计算机中最基本的数据单位是二进制位
针对二进制位进行操作、实现位控制的指令
- 逻辑运算指令
- 移位指令
- 循环移位指令
进行1位或若干位处理,采用位操作类指令
3.1 逻辑运算指令
逻辑与指令 AND
逻辑或指令 OR
逻辑非指令 NOT
逻辑异或指令 XOR
测试指令 TEST
对标志位的影响:
- 除NOT指令不影响标志外,其他逻辑指令
- 使OF=CF=0
- 根据结果按定义影响ZF、SF和PF
1. 逻辑与指令AND
逻辑与(逻辑乘)运算规则:
- 两位都是逻辑1,则结果是1;否则,结果是0
逻辑与指令AND:
- 按位进行逻辑与,结果返回目的操作数
AND reg,imm/reg/mem
;reg←reg ^ imm/reg/mem
AND mem,imm/reg
;mem←mem ^ imm/reg
设置CF=OF=0
影响SF,ZF和PF
AND指令的屏蔽作用
清除选定的位,并保存其他位
小写字符转换为大写
2. 逻辑或指令OR
逻辑或(逻辑加)运算规则:
- 两位都是逻辑0,则结果是0;否则,结果是1
逻辑或指令OR:
- 按位进行逻辑或,结果返回目的操作数
设置CF=OF=0
影响SF,ZF和PF
OR指令的置位作用
用于设置特定为,保留其他位
- mov al,11100011b
- or al,00000100b
3. 逻辑非指令NOT
逻辑非(逻辑反)运算规则: - 原来为0的位变成1,原来为1的位变成0
逻辑非指令NOT:
- 按位进行逻辑非,结果返回操作数
NOT reg/mem ;reg/mem←~reg/mem
不影响状态标志位
4. 逻辑异或指令XOR
逻辑异或(逻辑半加)运算规则:
- 两位不同(相异),则结果是1;否则,结果是0
逻辑异或指令XOR:
- 按位进行逻辑异或,结果返回目的操作数
设置CF=OF=0
影响SF,ZF和PF
使用xor清除寄存器
XOR之指令的可逆性
与0异或的位保持不变,与1异或的位变反
与同样的操作数执行两次异或后,结果不变
5. 测试指令TEST
按位进行逻辑与运算,不返回逻辑与结果
TEST reg,imm/reg/mem ;reg ^ imm/reg/mem
TEST mem,imm/reg ;mem ^ imm/reg
像AND指令一样来设置状态标志
常用于检测一些条件是否满足,一般后跟条件转移指令,目 的是利用测试条件转向不同的分支
3.2 移位指令
-
逻辑左移指令 SHL
-
逻辑右移指令 SHR
-
算术左移指令 SAL
-
算术左移指令 SAR
-
不带进位循环左移指令 ROL
-
不带进位循环右移指令 ROR
-
带进位循环左移指令 RCL
-
带进位循环右移指令 RCR
1. 移位指令
- 分逻辑(Logical)和算术(Arithmetic)移位
- 具有左移(Left)或右移(Right)操作
SHL reg/mem,i8/CL ;逻辑左移:最低位补0,最高位进入CF
SHR reg/mem,i8/CL ;逻辑右移:最高位补0,最低位进入CF
SAL reg/mem,i8/CL ;算术左移,与SHL是同一条指令
SAR reg/mem,i8/CL ;算术右移:最高位不变,最低位进入CF
目的操作数:寄存器或存储单元reg/mem
后一个操作数:移位位数i8/CL
移位指令的功能和示例
2. 循环移位指令
循环(Rotate)移位指令要将从一端移出的位返回 到另一端形成循环
分成不带进位循环移位和带进位循环移位
分别具有左移或右移操作
ROL reg/mem,i8/CL ;不带进位循环左移指令
ROR reg/mem,i8/CL ;不带进位循环右移指令
RCL reg/mem,i8/CL ;带进位循环左移指令
RCR reg/mem,i8/CL ;带进位循环右移指令
不带进位的循环左移指令
带进位的循环左移指令