1.8086基本指令
2.循环结构和分支结构及其程序的实现方法
8086 指令系统包括六大类指令:
具体可参考 emu8086 -> help -> documentation and tutorials -> Complete 8086 Instruction Set ⭐
功能:将源操作数的内容传送到目的操作数中。
功能:完成加、减、乘、除运算。
功能:(1)完成逻辑“反”、“与"、”或“、”异或“和测试;(2)对数据的移动
功能:执行跳转、调子程序、中断服务等。
汇编程序有4种基本结构:
无分支,无循环,无转移,直线运行到底。例如:
;
;*****************************************************************************
; @file add2.asm
; @author Xiaoxiao
; @date 2020-9-29
; @brief 顺序结构:两个十六进制数相加
; @blog https://blog.csdn.net/weixin_43470383/article/details/108625923
;*****************************************************************************
;
data segment
X DW 2020H ; 被加数
Y DW 2019H ; 加数
RESULT DW ? ; 分配数存放单元
data ends
stack segment
dw 128 dup(0)
stack ends
code segment
assume cs:code,ds:data ; 段假设
start:
MOV AX, DATA
MOV DS, AX
; 给除CS以外的其他用到的段的段寄存器赋值
MOV AX, X
ADD AX, Y
MOV RESULT, AX
; 处理并存储结果
MOV AH, 4CH
INT 21H
; 程序运行结束,关闭并返回操作系统
code ends
end start
指令执行过程中,需要进行判断、选择,来决定下一步执行的程序段。例如:
;
;*****************************************************************************
; @file pos_neg.asm
; @author Xiaoxiao
; @date 2020-9-29
; @brief 分支结构:判断MEMS单元数据,将结果存入MEMD单元。
; 若数据>0,结果为1,;若数据<0,结果为-1;若数据=0,结果为0
; @blog https://blog.csdn.net/weixin_43470383/article/details/108625923
;*****************************************************************************
;
DATA SEGMENT ;定义数据段
MEMS DB 08H ; 定义一个字节数据
MEMD DB 0 ; 定义一个字节数据,未赋值
DATA ENDS ; 数据段结束
CODE SEGMENT ;定义代码段
ASSUME CS: CODE, DS:DATA ;段属性说明
START: ;这里是程序的入口
MOV AX , DATA
MOV DS, AX ;初始化DS
MOV AL, MEMS ;将MEMS中数据送入AL中
CMP AL,0 ;将(Al)=08H与0进行比较
JGE NEXT ;≥0,转到标号NEXT处执行
MOV AL,-1 ; <0,结果为-1
JMP DONE ; 无条件跳转到标号DONE处执行
NEXT:
JE DONE ; =0,跳转到标号DONE处执行
MOV AL,1 ; >0,结果为1
DONE:
MOV MEMD,AL ; 将(AL)内容送入(MEMD)中
MOV AX, 4C00H
INT 21H ;程序结束,返回DOS
CODE ENDS ;代码段结束
END START ;汇编程序结束,指定程序入口地址
程序中的 JGE NEXT 指令即根据标志位 SF 和 OF 判断是否转移到程序段NEXT,如果SF = OF则转移
点击 single step 下一步执行 CMP AL,0
由于 SF = OF,执行 JGE NEXT 之后直接跳转到 NEXT,跳过
MOV AL,-1 ; <0,结果为-1
JMP DONE ; 无条件跳转到标号DONE处执行
接下来条件判断转移指令 JE DONE 类似,若标志位 ZF = 1,则转移。
满足一定条件时,重复执行一段程序。
循环控制有3种:
例程:
;
;*****************************************************************************
; @file scan.asm
; @author Xiaoxiao
; @date 2020-9-29
; @brief 循环结构:在ES中从2000H单元开始存放了10个字符,寻找其中有无"A"
; @blog https://blog.csdn.net/weixin_43470383/article/details/108625923
;*****************************************************************************
;
data segment
DATA1 DW 0
DATA2 DW 0
ends
stack segment
dw 128 dup(0)
ends
code segment
assume cs:code,ds:data,ss:stack
start:
mov ax, data
mov ds, ax
mov es, ax
MOV DI, 2000H
MOV BX, DI ; 偏移地址
MOV CX, 0AH ; 10个字符
MOV AL, 'A' ; 待检索数据
CLD ; (SI、DI)地址自增
REPNZ SCASB ; 重复
JZ FOUND
MOV DI, 0
JMP DONE
FOUND:
DEC DI
MOV DATA2, DI
INC DI
SUB DI, BX ; 搜索次数
DONE:
MOV DATA1, DI
HLT
mov ax, 4c00h
int 21h
ends
end start ; set entry point and stop the assembler.
程序中的 REPNZ SCASB 即根据标志位 CX 和 ZF 判断是否循环进行串搜索 SCASB 指令。每执行一次 SCASB 指令,CX寄存器自动减1,若 CX ≠ 0 且 ZF = 0,搜索操作继续进行。
CX ≠ 0 且 ZF = 0,经判断满足继续循环的条件。如此循环下去,CX 由原来的 000AH 变成 0000H 时,表明搜索完10次,结束循环。循环过程中,如果 CX ≠ 0 且 ZF = 1,表明搜索到“A”,循环也会终止。
下面是我们老师给出的程序,该程序的作用是判断随机数的奇偶性,分别存储至 odd_number 和 even_number ,并计数。
DATA SEGMENT
random_number DW 20 DUP(0)
odd_number DW 20 DUP(0)
even_number DW 20 DUP(0)
count DW 0
odd_count DW 0
even_count DW 0
DATA ENDS
STACK SEGMENT
DW 128 DUP()
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX,DATA
MOV DS,AX
MOV CX,20 ; 20次循环
LOOP_PRO:
CALL RAND ; 产生 WORD 随机数,保存在 BX 中
MOV SI, count
INC count
SHL SI, 1
MOV random_number[SI], BX
MOV AX, BX
AND AX, 0x0001
JZ EVEN_PRO
ODD_PRO:
MOV SI, odd_count
INC odd_count
SHL SI, 1
MOV odd_number[SI], BX
LOOP LOOP_PRO
JMP $
EVEN_PRO:
MOV SI, even_count
INC even_count
SHL SI, 1
MOV even_number[SI], BX
LOOP LOOP_PRO
JMP $
RAND PROC
PUSH CX
PUSH DX
PUSH AX
STI ; IF置1,允许响应可屏蔽中断
MOV AH,0 ;读时钟计数器值
INT 1AH
MOV BX,DX ;随机数存BX
POP AX
POP DX
POP CX
RET
RAND ENDP
CODE ENDS
END START
这段程序中包含1个子程序,RAND 子程序用于产生随机数。
LOOP_PRO 段调用 RAND 子程序,用于传递随机数,并判断奇偶性。
ODD_PRO 段用于处理奇数(存储数据并计数),EVEN_PRO 段用于处理偶数(存储数据并计数)。
参考:《微机原理与接口技术》(第4版)电子工业出版社