微机原理与接口技术总结笔记(二)
2019-06-06
课程复习笔记
上一篇:IA-32处理器架构
8086汇编程序设计
程序模板(Hello World)
.8086
.model small
.stack
.data
MSG BYTE "HELLO WORLD",0DH,0AH,'$'
.code
start:
MOV AX,@DATA
MOV DS,AX
MOV DX,OFFSET MSG
MOV AH 09H
INT 21H
MOV AX,4C00H
INT 21H
end start
伪指令和运算符
这一类指令都是直接在编译的时候把值算出来作为常量放进程序里面,而不是真正的运行时确定值的指令。
ORG
:规定目标程序和数据存放的偏移量,最开始有ORG 100H
那么定义的所有数据都从100H开始存$
:取当前指令的地址值,死循环:JMP $
PTR
:存储器取值指令,WORD PTR [1234H]
即从[1234H]取一个WORDEQU
:定义常量(数值或字符穿),常量值不占存储空间,而是在汇编的时候直接编译成直接数,类似C语言的宏,而且不允许重复定义=
:类似EQU,但可以重复定义,也不占存储空间OFFSET
:取偏移地址SEG
:取段基址
数据定义指令
-
定义数据类型
DB
,DW
,DD
-
重复定义DUP指令
BUFFER DB 100 DUP(?); BUFFER为首地址,100个字节,初始值未定 SW DB 90 DUP('A5',2),1 ; 271个字节 ARRAY DB 10 DUP('ABC',3 DUP(?)) ; 60个字节
通用指令集
- 数据传送指令
-
MOV:数据传送。
限制:立即数不能传递给段寄存器;存储器不能直接传递值;CS不能作为目标;数据长度必须一致
-
PUSH, POP, PUSHA, POPA:不能直接寻址,比如
PUSH 1234H
;不影响标志位; -
XCHG:交换
-
XLAT:换码指令(查表指令),操作为
(AL)=((BX)+(AL))
-
-
地址传送指令
- LEA:取有效地址(偏移地址)
-
算数运算指令
-
ADD, ADC, INC:加法。INC不影响CF; ADC带进位(CF);
-
SUB, SBB, DEC, CMP:减法。DEC不影响CF; SBB带借位(CF); CMP不影响值
-
MUL, IMUL:乘法。8位被乘数(AL)乘出16位(AX),16位被乘数(AX)乘出21位(DX,AX); SRC不是立即数;
-
DIV, IDIV:除法,正好和乘法扩位相反;SRC不是立即数
-
CBW, CWD:手动扩位。
-
-
位操作:
- NOT,AND,OR,XOR,TEST:逻辑位运算。NOT不影响任何标志;其他指令必然使CF=OF=0;TEST不改变源操作数
- SHL,SAL, SHR, SAR:非循环移位指令。逻辑(SHL和SHR)和算数的区别就是有没有符号
- ROL, ROR, RCL, RCR:循环移位指令
-
条件转移指令 JE, JNE, JA, JB等等,与CMP和TEST指令配合使用
-
循环指令LOOP, LOOPZ, LOOPNZ
-
子程序调用
- CALL:调用子程序,将IP(若段内调用)或IP和CS保存进栈再转移
- RET:操作和CALL相反;可以带一个立即数表示弹出栈参数长度。
-
中断指令INT,IRET
中断指令与子程序调用类似,但除了保护返回地址,还要保护标志寄存器进栈。
- IO指令 IN, OUT
子程序编程
一个带有子程序的汇编程序的典型结构如下:
.MODEL SMALL
.DATA
;...
.STACK
.CODE
SUB_PROC1 PROC ;通过PROC定义子程序开始
;...
RET
SUB_PROC1 ENDP ;通过ENDP定义子程序结束
MAIN: MOV AX, @DATA
MOV DS, AX
;...
CALL SUB_PROC1
传递参数的方法:
- 寄存器传递参数,这种最简单,没什么好讲的
- 存储器传递参数,再将参数区首地址通过寄存器或者堆栈传递,或者将参数区紧接定义在CALL指令之后,通过取出返回地址位置,就获得了参数区地址。
- 堆栈传递参数,这种也很简单,但要在RET指令后接参数长度。
保护现场:对需要用到的寄存器,在子程序最开始先入栈,结束时再使其出栈。
DOS功能调用
通过软中断INT 21H
和一些寄存器的值来调用对应的DOS操作系统的系统调用。重要的如下:
- AH=01H,读取一个输入存放在AL
- AH=02H,输出一个存放在DL的字符
- AH=09H,输出一个DS:DX为首地址,结束符为
$
的字符串 - AH=0AH,读取一个字符串,存放在首地址DS:DX
- AH=4CH,结束程序