汇编基础
- 80x86 寄存器组(8 位)
- AX 累加器用,常用于算术;乘除指令中存放操作数;I/O 指令中与外设传送信息
- BX 通用;计算存储器地址时,常用作基址寄存器
- CX 通用;保存计数值
- DX 通用;作双字长运算时把 DX 和 AX 组合在一起存放,DX 作为高位
- SP 堆栈指针,与 SS 联用
- BP 基址指针,与 SS 联用
- SI 源变址,与 DS 联用
- DI 目的变址,与 SS, ES 联用
- 80x86 专用寄存器组
- OF 溢出标志
- SF 符号标志(为负置 1)
- ZF 零标志(为零置 1)
- CF 进位标志
- AF 辅助进位标志(记录运算时第三位产生的进位值)
- DF 方向标志(为 1 时使每次操作后 SI 和 DI 减小)
- TF 陷阱标志
- IF 中断标志(为 1 时允许 CPU 响应可屏蔽中断请求)
实模式寄存器寻址
16d * 16位段地址 + 16位偏移地址 = 物理<
- 寻址方式
与数据有关
- 立即寻址(MOV AL,5)
- 寄存器寻址(MOV AX,BX)
- 直接寻址(MOV AX, [2000H])
- 寄存器间接(MOV AX,[BX])
- 寄存器相对(MOV AX,COUNT[SI 或 MOV AX,[COUNT + SI])
- 基址变址(MOV AX,[BX + DI] 或 MOV AX,BX)
- 相对基址变址(MOV AX, MASKBX 或 MOV AX,MASK[BX + SI] 或 MOV AX,[MASK + BX + SI])
- 比例变址(MOV EAX,COUNT[ESI * 4])
- 基址比例变址(MOV ECX,EAX)
- 相对基址比例变址(MOV EAX,TABLEEBP)
与转移地址有关
- 段内直接 NEAR / SHORT
- 段内间接 WORD PTR...
- 段间直接 FAR PTR...
- 段间间接 DWORD PTR...
PS:
- 操作数的数据类型需要匹配
- 指令系统
1. 数据传送指令
MOV OPRD1,OPRD2
功能:将 OPERD2 赋值给 OPERD1
参数:
- OPRD1:寄存器、存储器、累加器
- OPRD2:寄存器、存储器、累加器、立即数
- OPRD1 与 OPERD2 长度必须一致,即同为8为或16位
PS:
- 目的操作数不可用立即数和 CS 段
- 两个操作数中至少一个为寄存器
- 不允许段寄存器直接传送信息
- 该指令不影响标志位
MOVSX OPRD1,OPRD2 (x386)
功能:在 MOV 基础上用源操作数填充目的数高位
参数:同 MOV (x386)
MOVZX OPRD1,OPRD2 (x386)
功能:在 MOV 基础上用 0 填充目的数高位
参数:同 MOV
PUSH OPED
功能:将数压栈
下面以16位为例
(SP) = (SP) - 2
((SP) + 1,(SP)) = (SRC)
参数:
- OPRD:16位操作数、寄存器、存储器操作数
POP OPRD
功能:将数弹出栈
下面以16位为例
(DST) = ((SP) + 1,(SP))
(SP) = (SP) + 2
参数:同 push
XCHG OPRD1,OPED2
功能:交换数
参数:
- 同为寄存器
- 寄存器与存储器
2. 算术运算指令
ADD DST,SRC
功能:加法
参数:
- DST:被加数
- SRC:加数
ADC DST,SRC
功能:带进位加法
(DST)=(DST)+(SRC)+(CF)
参数:
- DST:被加数
- SRC:加数
- CF:进位
INC OPR
功能:自增 1
(OPR)=(OPR)+1
参数:
- OPR:被加数
XADD DST,SRC
功能:交换并相加
- TEMP=(DST)+(SRC)
- (SRC)=(DST)
- (DST)=TEMP
参数:
- DST:得到相加结果
- SRC:得到 DST
SUB DST,SRC
功能:减法
参数:
- DST:被减数
- SRC:减数
SBB DST,SRT
功能:带借位的减法
(DST)=(DST)-(SRC)-(CF)
参数:
- DST:被减数
- SRC:减数
- CF:借位
DEC OPR
功能:自减 1
参数:
- OPR:被减数
NEG OPR
功能:求补
(OPR)= -(OPR)
参数:
CMP OPR1,OPR2
功能:比较,后跟条件转移指令
(OPR1)-(OPR2)
* CMPXCHG DST,SRT
功能:比较并交换
参数:
* CMPXCHG8B DST,SRT
功能:比较并交换 8 字节指令
参数:
MUL SRC
功能:无符号数乘法
- (AX)=(AL)*(SRC)
- (DX,AX)=(AX)*(SRC)
- (EDX,EAX)=(EAX)*(SRC)
参数:
- SRC:不能为立即数,无符号
IMUL SRC
功能:带符号数乘法
(类似于 MUL )
参数:
- SRC:不能为立即数,有符号
DIV SRC
功能:无符号除法
(类似于 MUL )
参数:
IDIV SRC
功能:带符号除法
(类似于 MUL )
参数:
3. 逻辑运算指令
AND DST,SRC
功能:与
一般用法:
- 与自身,得全 1
- 与零,取反
- 与一,不变
OR DST,SRC
功能:或
一般用法:
- 或自身,不变
- 或零,不变
- 或一,得全 1
NOT OPR
功能:非
XOR DST,SRC
功能:异或
一般用法:
- 异或自身,得全 0
- 异或零,不变
- 异或一,取反
TEST OPR1,OPR2
功能:测试(得到与的结果,置条件码)
一般用法:
执行按位与运算,结果全 0 则 ZF = 1。
4. 移位指令
SHL OPR,CNT
SAL OPT,CNT
功能:逻辑/算术左移
左移右添 0
参数:
- CNT:1 或 CL
SHR OPR,CNT
功能:逻辑右移
右移左添 0,CF <- 低位
参数:
SAR OPR,CNT
功能:算术右移
右移左添高位自身,CF <- 低位
参数:
ROL OPR,CNT
功能:循环左移
CF <- 高位
参数:
ROR OPR,CNT
功能:循环右移
CF <- 低位
参数:
RCL OPR,CNT
功能:带进位循环左移
加上 CF 循环左移
参数:
RCR OPR,CNT
功能:带进位循环右移
加上 CF 循环右移
参数:
5. 串处理指令
MOVS DST,SRC
MOVSB DST,SRC
MOVSW DST,SRC
MOVSD DST,SRC
功能:串转移
参数:
CMPS SRC,DST
CMPSB SRC,DST
CMPSW SRC,DST
CMPSD SRC,DST (386)
功能:串比较
参数:
SCAS DST
SCASB DST
SCASW DST
SCASD DST (386)
功能:串扫描
(AL/AX/EAX)-(DST)
参数:
LODS SRC
LODSB SRC
LODSW SRC
LODSD SRC (386)
功能:串读取
(AL/AX/EAX)=(...)
参数:
STOS DST
STOSB DST
STOSW DST
STOSD DST (386)
功能:存入串
(...)=(AL/AX/EAX)
参数:
INS DST,DX
INSB DST,DX
INSW DST,DX
INSD DST,DX (386)
功能:串输入
(...)=(DX)
参数:
OUTS DX,SRC
OUTSB DX,SRC
OUTSW DX,SRC
OUTSD DX,SRC (386)
功能:串输出
(DX)=(...)
参数:
CLD
功能:使 DF = 0
STD
功能:使 DF = 1
REP
功能:前缀,重复
参数:
REPE/REPZ
功能:前缀,相等/为零则重复
参数:
REPNE/REPNZ
功能:前缀,不相等/不为零则重复
参数:
6. 控制转移指令
(以下指令均省略唯一操作数 OPR:转移的目标地址)
<<根据单个标志位的设置情况转移>>
JMP SHORT
JMP NEAR
JMP WORD PTR
JMP FAR PTR
JMP DWORD PTR
功能:无条件转移
- 段内直接短/近转移:
SHORT/NEAR:(IP)=(IP)+ 8/16 位偏移量 - 段内间接近转移:
WORD:(IP)=(EA) - 段内直接远转移:
FAR:(IP)=OPR 的段内偏移地址 - 段内间接远转移
DWORD:(IP)=(EA)
JZ
JE
转移条件:为零/相等
测试条件:ZF=1
JNZ
JNE
转移条件:不为零/不相等
测试条件:ZF=0
JS OPR
转移条件:为负则转移
测试条件:SF=1
JNS
转移条件:为正
测试条件:SF=0
JO
转移条件:溢出
测试条件:OF=1
JNO
转移条件:不溢出
测试条件:OF=0
JP
JPE
转移条件:奇偶位为 1
测试条件:PF=1
JNP
JPO
转移条件:奇偶位为 0
测试条件:PF=0
JB
JNAE
JC
转移条件:低于(<)或进位为 1
测试条件:CF=1
JNB
JAE
JNC
转移条件:不低于(>=)或进位为 0
测试条件:CF=0
<<比较无符号数根据结果转移>>
JB
JNAE
JC
转移条件:低于(<)或进位为 1
测试条件:CF=1
JNB
JAE
JNC
转移条件:不低于(>=)或进位为 0
测试条件:CF=0
JBE
JNA
转移条件:不高于(<=)
测试条件:CF||ZF = 1
JNBE
JA
转移条件:高于(>)
测试条件:CF||ZF = 0
<<比较带符号数根据结果转移>>
JL
JNGE
转移条件:小于(<)
测试条件:SF||OF = 1
JNL
JGE
转移条件:不小于(>=)
测试条件:SF||OF = 0
JLE
JNG
转移条件:不大于(<=)
测试条件:(SF||OF)||ZF = 1
JNLE
JG
转移条件:大于(>)
测试条件:(SF||OF)||ZF = 0
<<根据单个条件标志,设置目的字节为 1 >>
(以下指令均省略唯一操作数 DST:设置的目标地址)
SETZ
SETE
条件:结果为 0
SETNZ
SETNE
条件:结果不为 0
SETS
条件:结果为负
SETNS
条件:结果为正
SETO
条件:溢出
SETNO
条件:不溢出
SETP
SETPE
条件:奇偶位为 1
SETNP
SETPO
条件:奇偶位为 0
SETC
SETB
SETNAE
条件:低于(<)或进位位位 1 【可用于下面的无符号数比较】
SETNC
SETNB
SETAE
条件:不低于(>=)或进位位为 0【可用于下面的无符号数比较】
<<比较两个无符号数,根据结果设置目的字节为 1 >>
SETBE
SETNA
条件:不高于(<=)
SETNBE
SETA
条件:高于(>)
<<比较两个带符号数,根据结果设置目的字节为 1 >>
SETL
SETNGE
条件:小于(<)
SETNL
SETGE
条件:不小于(>=)
SETLE
SETNG
条件:不大于(<=)
SETNLE
SETG
条件:大于(>)
<<循环>>
LOOP OPR
LOOPZ/LOOPE OPR
LOOPNZ/LOOPNE OPR
循环条件:
- 计数器不为 0
- 为零或相等
- 不为零或不相等
参数:转移目的地址/循环代码段名
<<子程序>>
CALL DST
功能:调用
参数:子程序名
RET
RET EXP
转移条件:无
参数:
- EXP:立即数
7. 中断指令
INT
INT TYPE
参数:
- TYPE 常数或常数表达式
INTO
中断条件:溢出
IRET
IRETD
转移条件:从中断返回指令(16/32位)
8. 标志处理指令
CLC
功能:CF = 0
CMC
功能:CF = -CF
STC
功能:CF = 1
CLD
功能:DF = 0
STD
功能:DF = 1
CLI
功能:IF = 0
STI
功能:IF = 1
9. 杂项操作
NOP
无操作
HLT
停机
ESC
换码
WAIT
等待
LOCK
封锁
BOUND
界限
ENTER
建立堆栈帧
LEAVE
释放堆栈帧
汇编程序
完整版
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
;此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START
简化版
.MODEL SMALL
.DATA
;此处输入数据段代码
.STACK
;此处输入堆栈段代码
.CODE
.STARTUP
;此处输入代码段代码
.EXIT
END
完整版段定义(数据段、堆栈段、代码段)
声明
segmentName SEGMENT [align_type][combine_type][use_type]['class']
...
segmentName ENDS
明确关系
ASSUME assignment, ... , assignment
(assignment 即 segmentRegisterName : segmentName 如 DS : DATAS)
声明的其他参数
- align_type 定位类型(可选: PARA、 BYTE、 WORD、 DWORD、 PAGE)
- combine_type 组合类型(可选: PRIVATE、 PUBLIC、 COMMENT、 AT expression、 MEMORY、 STACK)
- use_type 使用类型(可选: USE16、 USE32)
- 'class' 类别
简化版定义
.MODEL memory_model[, model options]
参数可选或设置
- Tiny 近访问
- Small 近访问(常用)
- Medium 数据近访问、代码可远访问
- Compact 代码近访问、数据可远访问
- Large 远访问
- Huge 数据段超过 64k,远访问
- Flat 允许 32位偏移量(DOS 不支持)
- model options 允许用户指定三种选项:高级语言接口、操作系统和堆栈距离
数据定义
- DB 一个字节-8
- DW 一个字 - 16
- DD 双字 - 32
- DF 6个字节的字 - 48
- DQ 4字 - 64
- DT 10字节 - 80
操作数定义
- DUP(?) 占位(保留位);可嵌套
- 字符串
- 立即数
表达式赋值(EQU)
Expression_name EQU Expression
地址计数器
- $ 获取当前地址计数器的值
- ORG 设置当前地址计数器的值
- EVEN 使下一个变量或指令开始于偶数字节地址
- ALIGN 使下一个变量或指令开始于 4 的倍数字节地址
基数控制
.RADIX expression
操作项
- +、-、*、/ 和 MOD 基本运算
- SHL、 SHR 移位
- EQ、 NE、 LT、 GT、 LE、 GE 关系操作符
- TYPE 变量类型字节数
- LENGTH 变量单元数
- SIZE 为 LENGTH 和 TYPE 的乘积
- OFFSET 变量或标号偏移地址
- SEG 变量或标号段地址
- PTR
- SHORT
- THIS
- HIGH
- LOW
- HIGHWORD
- LOWWORD
输入输出程序设计
直接存储器存取方式(DMA、 其他CPU传输方式:查询、中断)
- DMA 向 CPU 发出 HOLD 信号,请求使用总线
- CUP 发出响应信号 HOLD 给 DMA,并让出总线
- 传输数据的地址通过地址总线发出
- 传输的数据字节通过数据总线传送
- 地址寄存器 +1,指向下一个要传送的字节
- 字节计数器 -1
- 如果字节计数器非 0, 转向第 3 步
- 否则,DMA 撤销总线请求信号 HOLD,传送结束
I/O 端口
三种寄存器
- 数据寄存器 - 用于数据缓冲
- 状态寄存器 - 用于保存设备和接口的状态信息、供 CPU 对外设进行测试
- 命令寄存器 - 用于保存 CPU 发出的命令以控制接口和设备的操作
中断传送
硬件中断
- 可屏蔽 - 8259 控制位(中断允许位 IF)
- 非屏蔽 - 2#
软件中断
- INT
- CPU 某些错误引起
- DEBUG - 单步、 断点
中断过程
- 取中断类型号 N
- 标志寄存器 FLAGS 内容入栈
- 当前代码段寄存器 CS 内容入栈
- 当前指令计数器 IP 内容入栈
- 禁止硬件中断和单步中断 IF=0,TF=0
- 从中断向量表中取 4 N 的字内容送 IP,取 4 N + 2 中的字内容送 CS
- 转中断处理程序
BIOS 和 DOS 中断(略)
总结
指令系统
- CL * 开头的为 clear (复位)对应的标志位(CLD, CLC, CLI, ...)
- ST * 开头的为 set (置位)对应的标志位(STD, STC, STI ...)
- 无符号数比高低用 A B (above, below)
- 有符号数比大小用 G L (great, LESS)
地址疑问
- IP 总是指向 CS (代码段)将要执行的(下一行)代码的地址
- SP 总是指向刚 push 进去的内容所处位置
- DB 与 DW 变量的 SI 偏移量不同(1、 2)
程序设计
子程序传参三种方法:
- 寄存器(适用于少变量)
- 变量(仅限于同一源文件)
- 地址表(仅限于同一模块)
- 堆栈或参数地址(适用于多模块)
进制转换
- 输入二进制:边存储边左移位
- 输入十进制:乘上权值(10)再累加
- 输入十六进制:高于 9 则转换,乘上权值(16)再累加
- 输出二进制:边左移位边输出
- 输出十进制:除法并输出模 10 的值
- 输出十六进制:除法并输出模 16 的值(注意转换)
涉及算法
- 冒泡排序
- 折半查找
CPU与外设传送数据方式
- DMA --直接存储器存取
- 查询
- 中断