微机接口笔记3-指令系统与汇编语言

寻址方式

寻址方式 操作数地址 指令格式举例
立即寻址 操作数由指令给出 MOV DX, 100H
寄存器寻址 操作数在寄存器中 ADD AX, BX
直接寻址 由指令给出操作数有效地址 MOV AX, [100]
寄存器间接寻址 PA=(DS)*16+(BX) MOV AX, [BX]
寄存器相对寻址 PA=(DS)*16+(BX)+位移量 MOV AX, MESS[SI]
基址变址寻址 PA=(DS)*16+(BX)+(DI) MOV AX, [BX+DI]
相对基址变址寻址 PA=(DS)*16+(BX)+(DI)+位移量 MOV AX, BUFF[BX+DI]

汇编语言

常量

整数:二进制B,八进制Q,十进制D或不带,十六进制H

字符串:连续字节单元,每个单元均存放ASCII码,用单引号包括

数据定义

为程序中的数据分配空间并设置内存单元的初始值

  • DB 定义字节
  • DW 定义字
  • DD 定义双字
  • DUP 分配一段数据块空间

表达式

算术运算符

  • + — * / MOD SHL

逻辑运算符

  • AND
  • OR
  • NOT
  • XOR

关系运算符

  • EQ
  • NE
  • LT
  • LE
  • GT
  • GE

分析运算符

  • SEG 求段地址
  • OFFSET 求偏移地址
  • TYPE 求符号名称类型
  • LENGTH 求符号名分配项数,只对DUP有效否则为1
  • SIZE 求符号名分配字节数,只对DUP有效否则为1

综合运算符

  • PTR

伪指令

  • 地址计数器伪指令$:表示位置计数器的值,为程序下一个所能分配的储存单元的偏移地址
  • 地址对准器位指令ORG:指出源程序数据块起点,可改变位置计数器的值
  • 符号定义位指令EQU:给表达式定义一个等价的符号名
  • 解除伪指令PURGE:解除EQU定义
  • 段定义位指令SEGMENT
  • 简约段定义伪指令.386,.DATA,.CODE,.STACK
  • 过程定义伪指令PROC...RET ENDP
  • 汇编程序结束伪指令END

指令系统

通用传送指令

  • MOV

堆栈操作指令

按字或双字进行,不能按字节进行;后进先出;CS值能直接保存到堆栈,但是堆栈值不能POP到CS

  • PUSH
  • POP
  • PUSHA
  • POPA
  • POSHAD
  • POPAD

交换指令

  • XCHG 目的操作数与源操作数不能均为内存单元,IP不能交换

输入输出指令

只能用累加器作为执行过程;直接IO时范围0-255;间接IO时必须用DX;

  • IN
  • OUT

换码指令

  • XLAT 查表转换指令 MOV AL, DS:[BX +AL]
  • XLATB

地址传送指令

  • LEA 取有效地址
  • LDS
  • LES
  • LSS
  • LFS
  • LGS

标志传送指令

  • LAHF 读标志指令
  • SAHF 设置标志指令
  • PUSHG 对标志寄存器的推入
  • POPF 对标志寄存器的弹出
  • PUSHFD
  • POPFD

加法指令

  • ADD 不带进位加法
  • ADC 带进位加法,CF进位标志
  • XADD 字节交换加法
  • INC 自增1

减法指令

  • SUB 不带借位的减法
  • SBB 带借位的减法
  • DEC 自减1
  • NEG 求补
  • CMP 比较
  • CMPXCHG 比较交换,若相等则把源操作数送到目的操作数,若不相等则把目的操作数送累加器
  • CMPXCHG8B

乘法指令

  • MUL 无符号乘法
  • IMUL 有符号乘法

除法指令

  • DIV 无符号除法
  • IDIV 有符号除法

类型转换指令

  • CBW AL符号位扩展到AH
  • CWD AX符号位扩展到DX
  • CWDE AX符号位扩展到EAX
  • CDQ EAX符号位扩展到EDX

BCD码指令

  • AAA
  • DAA
  • AAS
  • DAS
  • AAM
  • AAD

逻辑指令

  • AND 按位与,结果放在目的操作数
  • TEST 按位与,结果不保存,影响标志位
  • OR 按位或
  • XOR 按位异或
  • NOT 按位非

移位指令

  • SAL 算术左移
  • SAR 算术右移
  • SHL 逻辑左移
  • SHR 逻辑右移
  • ROL
  • RCL
  • ROR
  • RCR
  • SHLD
  • SHRD

串操作指令

  • MOVSB
  • MOVSW
  • REP
  • REPE/REPZ
  • REPNE/REPNZ
  • CMPSB/CMPSW 字符串比较指令
  • SCASB/SCASW 字符串检索指令
  • LODSB/LODSW 取字符串指令
  • STOSB/STOSW 存字符串指令

控制转移指令

  • JMP 无条件转移指令
  • JZ/JE 结果为0则转移
  • JNZ/JNE 结果不位0则转移
  • JS 符号标志SF=1则转移
  • JNS SF=0则转移
  • JO OF=1则转移
  • JNO OF=0则转移
  • JP 奇偶标志PF=1则转移
  • JNP PF=0则转移

  • JB/JNAE 低于,则转移

  • JNB/JAE 不低于,则转移
  • JBE/JNA 不高于,则转移
  • JNBE/JA 高于,则转移

  • JL/JNGE 小于,则转移

  • JNL/JGE 不小于,则转移
  • JLE/JNG 不大于,则转移
  • JNLE/JG 大于,则转移

  • JCXZ CX为0,则转移到

  • CALL 子程序调用指令

  • RET
  • LOOP
  • INT
  • IRET

  • HLT 暂停指令

标志位操作指令:

  • STI IF置1
  • CLI IF清0
  • CLD DF清0
  • STD DF置1
  • CLC CF清0
  • STC CF置1
  • CMC CF求反

汇编例程

5个连续字节单元累加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
DATA    SEGMENT	         ;定义数据段
D1 DB 5 DUP (?) ;连续的字节单元
CC EQU $-D1 ;对单元计数
SUM DW 0 ;为结果保留一个字
DATA ENDS ;数据段定义结束

STACK SEGMENT ;定义堆栈段
DB 100 DUP (?) ;100字节的栈空间
STACK ENDS ;堆栈段定义结束

CODE SEGMENT ;定义代码段
ASSUME DS:DATA, SS:STACK, CS:CODE ;对各段进行说明
BEGIN:
MOV AX, DATA ;DS初始化为DATA
MOV DS, AX
LEA SI, D1 ;预置源数据的指针
MOV CX, CC ;预置次数,这里是5次
CLD ;(DF)=0,串指针自动增量
LODS BYTE PTR [SI] ;取一个数并修改指针
MOV AH, 0 ;清AX的高字节
CLC ;清CF位
AGAN:
ADC SUM, AX ;累加
LODS BYTE PTR [SI] ;再取数并修改指针
LOOP AGAN ;控制循环
MOV AH, 4CH ;完成,返回DOS
INT 21H
CODE ENDS ;代码段结束
END BEGIN ;整个程序结束

用查表方法将一个十六进制数转为对应的ASCII码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DATA    SEGMENT
TABLE DB 30H,31H,32H,33H,34H,35H
DB 36H,37H,38H,39H,41H,42H
DB 43H,44H,45H,46H
HEX DB 4
ASC DB ?
DATA ENDS

STACK1 SEGMENT
DW 20H DUP(0)
STACK1 ENDS

COSEG SEGMENT
ASSUME CS:COSEG,DS:DATA,SS:STACK1
START:
MOV AX, DATA
MOV DS, AX
LEA BX, TABLE ;取表的基址
XOR AH, AH ;异或,归零
MOV AL, HEX ;拿到指定的十六进制数
ADD BX, AX ;BX=BX+AX 找到表中的第几位
MOV AL, [BX] ;得到指定的ascii码并转移到AL中
MOV ASC, AL ;放入ASC中得到结果
COSEG ENDS
END SATRT

产生n个裴波纳契数数列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
DATA    SEGMENT
FIBONA DW 100H DUP(0)
NUM DB 20H
DATA ENDS

STACK1 SEGMENT
DW 20H DUP(0)
STACK1 ENDS

COSEG SEGMENT
ASSUME CS:COSEG,DS:DATA
BEGIN:
MOV AX,DATA
MOV DS,AX
MOV CL,NUM ;指定需要产生NUM个数
XOR CH,CH ;CH清零
LEA DI,FIBONA ;
MOV AX,0 ;AX,BX为斐波那契数列头两个
MOV BX,1
LOP:
MOV [DI],AX ;此时[DI]为FIBONA数组的第一个,这里放入第一个数0
XCHG AX,BX ;交换AX,BX
ADD AX,BX ;AX,BX相加
ADD DI,TYPE FIBONA ;FIBONA一个元素大小为2,DI+=2
LOOP LOP
MOV AH,4CH ;结束
INT 21H
COSEG ENDS
END BEGIN

找出最大数

编一程序,在以BUF为首地址的字节单元中存放了COUNT个无符号数,找出其中最大数送MAX单元。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
DATA     SEGMENT
BUF DB 1,2,3,4,5,23,55,88
COUNT EQU $-BUF ;要统计的数有多少个
MAX DB ?
DATA ENDS

CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV BX,OFFSET BUF ;得到BUF偏移地址,即第一位
MOV CX,COUNT – 1 ;
MOV AL,[BX] ;第一个数放入AL
LOOP1: INC BX ;偏移地址+1得到第二个数
CMP AL,[BX] ;比较第一个数与第二个数大小
JAE NEXT ;不小于则转移即第一个数大
MOV AL,[BX] ;否则第二个数大,将其加入比较队列
NEXT: DEC CX ;计数器-1
JNZ LOOP1 ;回到LOOP1比较下一个数
MOV MAX,AL ;循环结束后得到最大数在AL里
MOV AH,4CH
INT 21H
CODE ENDS
END START

统计负数和正数的个数

在以BUF为首地址的字节单元中存放了COUNT个字节数据,编一程序分别统计负数和正数的个数送MINUS和PLUSMAX单元。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
DATA     SEGMENT
BUF DB 1,-22,3,4,5,23,55,88
COUNT EQU $-BUF ;要比较的数的个数
PLUS DB ? ;正数个数
MINUS DB ? ;负数个数
DATA ENDS

CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV BL,0 ;存负数个数
MOV DL,0 ;存正数个数
MOV SI,OFFSET BUF ;拿要比较的数组
MOV CX,0
LOOP1: MOV AL,[SI]
CMP AL,0 ;将第一个数与0比较
JGE NEXT0 ;大于等于0则跳转?
INC BL ;负数个数+1
JMP NEXT1 ;跳转到比较下一个数
NEXT0: INC DL ;正数个数+1
NEXT1: INC SI ;比较下一个数
INC CX ;这里没有使用LOOP而是用CX计数
CMP CX,COUNT ;比较了指定个数后跳转结束
JL LOOP1
MOV MINUS,BL
MOV PLUS,DL
MOV AH,4CH
INT 21H
CODE ENDS
END START