8086CPU寄存器
8086:16位,4.77MHz~10MHz,16根数据线,20根地址线
AX/AL:乘除法指令中用作累加器,IO指令中用作数据寄存器,可显式或隐含调用
AH:在LAHF用作目的寄存器,隐含调用。
AL:在BCD码用做累加器,隐含调用。
BX:在存储器寻址用作地址/基址寄存器,显式调用。在XALT用作基址寄存器,隐含调用
CX:循环计数器,隐含
CL:在移位、循环移位中用作移位次数,显式
DX:在I/O指令用作地址寄存器,显式调用。在乘除法用作辅助累加器,隐含调用
BP:堆栈段基址寄存器,显式。
SP:堆栈指针,隐含
SI:字符串操作源地址寄存器,隐含。存储器寻址用作地址寄存器,显式。
DI:字符串操作目的变址寄存器,隐含。存储器寻址用作地址寄存器,显式。
CS:代码段寄存器。
SS:堆栈段
DS:数据段
ES:附加段
IP:即将执行的指令的偏移地址,不能读/显式设定
PSW:
15~12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
OF | DF | IF | TF | SF | ZF | AF | PF | CF | ||||
overflow | 指针方向 | 中断 | 单步 | sign | zero | 辅助进位 | 最低位字节“1“个数 | carry | ||||
IF=1,允许中断 | TF=1,单步 | 低4位对高四位进位 | 为偶数时PF=1 |
8086的控制与时序
总线读周期
总线写周期
模板与变量
调试流程:编辑(.asm),汇编(.obj),连接(.exe),执行。
调试debug模式下所有数据16进制。
伪指令:参数是常量、变量名,参数间用逗号分隔
模板:
.model small .stack 100 .data ;//数据区 .code start: mov ax,@data mov ds,ax ;//逻辑代码 mov ax,4c00h int 21h end start
指令
寻址
指令格式:op dst src
立即寻址:操作数在指令中
寄存器寻址:用作dst,src
,除了IP、PSW,都可以寄存器寻址。CS不能为dst
存储器寻址:dst和src不能同为存储器寻址
直接寻址:EA=8/16位位移量,例如:MOV AX,[2000H]
寄存器间接寻址:EA=BX/BP/SI/DI。例如:MOV AX,[BX]
寄存器相对寻址:EA=BX/BP/SI/DI+8/16位。例如:MOV AX,06H[SI]
基址变址寻址:EA=BX/BP+SI/DI。例如:MOV AX,[BP][SI]
相对基址变址寻址:EA=BX/BP+SI/DI+8/16位移量
使用BP时,隐含段位SS。其余隐含段为DS。允许段超越。
EA可为数值,可为变量名(符号地址)
(CS,IP)不为目的操作数。数据类型要一致。
例如,MOV [BX][SI],1
错误,类型不明确。
XCHG OPR
1 _11OPR
2 _22交换数值(不能同为mem,不能用seg、ip、imm)
XLAT
:AL
← \leftarrow←[(BX)+(AL)]
堆栈从较大地址分配使用,向上生长。
PUSH src
:SP
← \leftarrow←SP-2
,((SP)+1,(SP))
← \leftarrow←src
(不能同为imm),必须16位
POP dst
:dst
← \leftarrow←((SP)+1,(SP))
,SP
← \leftarrow←SP+2
,CS不能为dst
LEA reg,src
,reg不为seg,src必须为mem(lea传送地址,mov传送内容)
LDS
:reg
← \leftarrow←src
,dst
← \leftarrow←src+2
。src:reg,mem,imm。dst:mem,reg
pushf/popf:保存/恢复主程序flag
运算
CBW
:AL
→ \rightarrow→AX
,CBW
:AX
→ \rightarrow→DX,AX
加减法:OP dst,src
,src和dst不能同为reg/为seg
INC
不影响CF。
求补:NEG opr
(opr
← \leftarrow← 0-opr)
乘法:无符号数为MUL src
,有符号数为IMUL src
,src为reg/mem。为mem时,明确类型用ptr。
无符号除:DIV src
。有符号除:IDIV src
NOT不影响flag。其余逻辑运算清零CF/OF,但SF/PF/ZF根据结果设置。
移位:OP dst,src
其中src为1或CL。dst为mem且应当指明类型。左移为*2,右移为/2。带进位循环移位可实现高精度。
##
转移
转移:直接寻址(标号)、间接寻址(reg、mem)
JMP short
8位,
JMP 标号
:IP
← \leftarrow←IP+label
相对于当前IP偏移,CS不变
JMP NEAR PTR 标号
:16位范围,不包含byte/dword,为word
JMP FAR PTR 标号
:IP
← \leftarrow←offset next
,CS
← \leftarrow←seg next
无符号数:JB/JC/JNAE
低于,JNB/JAE/JNC
高于等于,JBE/JNA
低于等于,JNBE/JA
高于
有符号数:JL/JNGE
小于,JNL/JGE
大于等于,JLE/JNG
小于等于,JNLE/JG
大于
JCXZ
CX=0则转移,JE
相等,JNE
不相等,JP
PF=1则转移(1的个数为偶数)
LOOP
:只短转移
LOOP opr
:CX≠ \ne= 0
LOOPZ opr
(ZF=1且CX≠ \ne= 0)
LOOPNZ opr
(ZF=0且CX≠ \ne= 0)
LOOP
相当于:
DEC CX JNZ 标号
子程序
CALL
子程序名(段内直接调用):SP
← \leftarrow←SP-2
,(SS:IP)
← \leftarrow←IP
,IP
← \leftarrow←子程序
RET
:(IP)
← \leftarrow←(SS:IP)
,(SP)
← \leftarrow←(SP)+2
RET n
:(IP)
← \leftarrow←(SS:IP)
,(SP)
← \leftarrow←SP+2+n
段间调用
call
子程序名
(SP)
← \leftarrow←(SP-2)
(SS:SP)
← \leftarrow←(CS)
(IP)
← \leftarrow←子程序入口
(CS)
← \leftarrow←子程序段
(先压段后压偏移)
段间返回
ret
(IP)
← \leftarrow←(SS:SP)
(SP)
← \leftarrow←(SP)+2
(CS)
← \leftarrow←(SS:SP)
(SP)
← \leftarrow←(SP)+2
先取偏移后取段
ret n
:在csn出栈还会(SP)
← \leftarrow←(SP)+n
I/O中断
物理地址=类型码*4
中断类型码/中断向量号 0~255
每个中断向量4byte,高字CS,低字IP
int:将flag入栈,清除TF、IF。CS入栈,IP入栈,最后跳转
into:检测OF。若溢出,中断类型码为4
iret:IP出栈、CS出栈,恢复flags
控制:hlt(停止) nop(空操作) wait(等到test=0)
I/O调用:参数装入指定reg,功能号装入AH
子功能装入AL,调用,返回。
int 21H:
AH | 功能 | 参数 | 返回 |
1 | 输入字符,回显 | 无 | AL=字符 |
6 | 读字符,回显 | DL=0FFH | AL=字符,ZF=0。若无字符,AL=0,ZF=1 |
7 | 输入字符,不回显 | 无 | AL=字符 |
A | 输入字符到缓冲区 | DS:DX=缓冲区首地址 | |
2 | 显示字符一个(检验ctrl-break) | DL=字符ASCII | |
9 | 显示字符串 | DS:DS=串首地址,以$结束 |
0DH:回车(光标回到本行第一个字符)
0AH:换行
输出文字
lea bx,string mov cx,7;7为长度 one:mov dl,cs:[bx] mov ah,2 int 21H inc bx loop one string db "hello" end start
输出串
lea dx,string mov ah,9 int 21h string db 0DH,0AH,"hello",0DH,0AH,'$'
输入5个数
mov cx,5 mov sum,0 one:mov ah,1 int 21h and al,0fh add sum,al loop one
从键盘输入至多5个数
lea dx,buffer mov ah,0ah int 21H mov sum,0 mov cl,buffer+1 mov ch,0 lea bx,buffer+2 one: mov al,[bx] and al,0fh add sum,al inc bx loop one
程序逻辑语句
双分支结构一定要跳过另一个分支体。
大小写字母ASCII码差值20H,仅D 5 D_5D5位不同。
用地址表实现多分支转移。数据段:addtbl dw f1,f2,f3
程序段:jmp addtbl[bx]
循环:
do-while型初始化、工作、修改、控制。
while型循环:初始化、控制、跳出、工作、修改、跳回控制。
无符号字数组以-1为结束,求平均值
lea bx,array one:cmp word ptr[bx],-1 je done;//数组结束 add ax,[bx] adc dx,0;保留进位 inc cx;//数组元素个数 add bx,2 jmp one done:jcxz null div cx mov avg,ax jmp exit null:mov avg,-1
square proc near push cx push bx mov bx,ax;要求的数 mov al,0 mov cx,1 next:sub bx,cx jb done inc al add cx,2 jmp next done: pop bx pop cx ret square endp
mov ax,x cwd idiv y add ax,w mov bx,100 imul bx mov cx,ax mov bx,dx mov ax,r cwd add ax,cx adc dx,bx mov z,ax mov z+2,dx
中断服务程序示例
point dw 0 temp db 500 dup(?) intproc proc far push ds push ax sti mov ax,seg temp mov ds,ax mov bx,point in al,60H mov temp[bx],al int pont cli mov al,20H out 20H,al pop ax pop ds iret intproc endp