microcomputer_principle_09_汇编语言与系统功能调用
Carpe Tu Black Whistle

汇编语言源程序

  1. 汇编程序与汇编语言源程序
  2. 汇编语言语句类型与格式
  3. 汇编语言语句中的操作数

  • 汇编语言源程序 –> 用助记符编写
  • 汇编程序 –> 源程序的编译程序

image


汇编语言程序设计与执行过程

  • 输入汇编语言源程序(EDIT) –> 源文件.ASM
  • 汇编(MASM) –> 目标文件.OBJ
  • 链接(LINK) –> 可执行文件.EXE
  • 调试(TD) –> 最终程序

汇编语言语句语句类型和格式

汇编语言语句类型

  • 指令性语句
    • CPU执行的语句,能够生产目标代码
  • 指示性语句
    • CPU不执行,而由汇编程序执行的语句,不生成目标代码
      (告诉编译器,分配多大内存空间,程序从哪儿开始,到哪儿结束)

汇编语言语句格式:

汇编语言语句格式:

指令性语句:

[标号: ][前缀]助记符[操作数],[操作数][;注释]

标号:指令的符号地址,标号要有冒号

指示性语句格式:

[名字] 伪指令助记符 操作数[, 操作数, …][;注释]

指示性语句中至少有一个操作数
操作数个数不受2个限制,受逻辑段限制

所有操作数个数加在一起,不能超过64K字节

名字:变量符号地址(为区别标号,后面不能有冒号)

汇编语言语句中的操作数

  1. 寄存器
  2. 存储器单元
  3. 常量
  4. 变量或标号
  5. 表达式

常量

  • 数字常量
  • 字符串常量 –> 用单引号引起的字符或字符串
  • e.g.
    • MOV AL, ‘A’ –> AL=41H
  • e.g.
    • 定义字符串: ‘ABCD’–>汇编时被译成对应的ASCII码,41H,42H,43H,44H
    • MOV AL, 0ABCDH

如果以字符开头的16进制数,要用0开头,否则会被当作名字/标志

变量

内存单元的符号地址,为存储器操作数

  • 变量属性

段 值 ———— 变量所在段的段地址
偏移量 ———— 变量所指单元的偏移地址
类 型 ———— 字节型、字型和双字型

内存单元的符号,形式上只代表一个单元
不同的定义模式下,代表着一串地方

表达式

  • 算术运算
  • 逻辑运算
  • 关系运算
  • *取值运算和属性运算
  • 其他运算

取值运算符

  • 用于分析存储器操作数的属性
    • 获取变量的属性值

OFFSET –> 取得其后比那两或标号的偏移地址
SEG –> 取得其后变量或标号的段地址

  • e.g.
    1
    2
    3
    4
    MOV AX, SEG DATA
    MOV DS, AX ; 取变量的段地址并送给DS
    MOV BX, OFFSET DATA ; 取变量的偏移地址送给BX
    ; 完全可以等价于 LEA BX, DATA

取变量的段地址只能通过SEG
取变量的偏移地址,可以用LEA 或者 OFFSET

属性运算符

  • 用于指定其后存储器操作数的类型
  • 运算符:PTR
  • e.g.:
    • MOV BYTR PTR[BX], 12H –> 指定存储器操作数[BX]为“字节型”

伪指令

伪指令是指示性语句的核心

  • 由汇编程序执行的“指令系统”
  • 作用:
    • 定义变量;
    • 分配存储区;
    • 定义逻辑段;
    • 指示程序开始和结束;
    • 定义过程等。

帮助计算机理解助记符指令编写的汇编语言源程序


  • 数据定义伪指令
  • 符号定义伪指令
  • 段定义伪指令
  • 结束伪指令
  • 过程定义伪指令
  • 宏命令伪指令

数据定义伪指令

用于定义数据区中变量的类型及其所占内存空间大小

  • format:
    [变量名] 伪指令助记符 操作数,… ;[注释]

伪指令助记符 –> 定义变量类型
操作数 –> 变量值,可以是常数,表达式或字符串。

操作数大小不能超过伪指令助记符所限定的范围
变量的类型及其操作数的个数决定了该变量所在内存空间的大小

数据定义伪指令助记符

  • DB(Define Byte): –> 指向的每个操作数占1个字节单元
    • 定义的变量为字节型
  • DW(Define Word): –> 指向的每个操作数占一个字单元
    • 定义的变量为字类型
  • DD(Define Double Word):
    • 定义的变量为双字型
  • DQ(Define Quadword):
    • 定义的变量为4字型
  • DT(Define Tenbytes):
    • 定义的变量为10字节型

e.g.

1
2
3
DATA1 DB 11H, 22H, 33H, 44H
DATA2 DW 11H, 22H, 3344H ; 定义为**字单元**,故为0011H,0022H
DATA3 DD 11H*2, 22H, 33445566H ; 11H*2 相当于表达式

image

数据定义伪指令的几点说明

  • 数据定义伪指令决定所定义变量的类型;
  • 定义字符串必须用DB伪指令
  • e.g.
    • DATA1 DB ‘ABCD’, 66H

不用DB定义字符串,会报错

image

DUP

重复操作符: DUP, duplication

当同样的操作数重复多次时,可以使用重复操作符。

  • 作用:
    • 为一个数据区的各单元设置相同的储值
  • format:
    [变量名] 伪指令助记符 n DUP (初值[,初值,…])
    n –> 重复的次数
  • e.g.
    • M1 DB 10 DUP(0)

常用于声明一个数据区

?

表示随机值,预留存储空间

  • e.g.
    • MEM1 DB 34H, ‘A’, ? ; 随机数,占一个字节单元
    • DW 20 DUP(?) ; 预留40个字节单元,每单元为随机值
1
2
3
4
M1 DB 'How are you?'
M2 DW 3 DUP(11H), 3344H
DB 4 DUP(?)
M3 DB 3 DUP(22H, 11H, ?)

image

符号定义伪指令

将表达式的值赋给一个名字。当源程序中需多次引用某一表达式时,可以利用EQU伪指令,用一个符号代替表达式,以便于程序维护。

  • format:
    • 符号名 EQU 表达式
  • manipulation:
    • 用符号名取代后边的表达式,不可重新定义
  • e.g.
    • CONSTANT EQU 100

EQU说明的表达式不占用内存空间

段定义伪指令

  • 在汇编语言源程序中定义逻辑段
    • 说明逻辑段的起始和结束
    • 说明不同程序模块中同类逻辑段之间的联系形态
  • format:
    1
    2
    3
    4
    5
    段名 SEGMENT [定位类型][组合类型]['类别']
    .
    .
    .
    段名 ENDS

段名–> 逻辑段段段基地址, 段基地址的具体值,对程序员透明
定位类型 –> 说明逻辑段的起点,默认为节边界起始,一节是16bit,所以每个逻辑段地址,都要被16整除
组合类型 –> 装入内存时,各逻辑段的组合方式,默认不组合
类别 –> 链接时,不同程序模块中的同类逻辑段将被装入连续存储区

e.g.

1
2
3
4
5
DATA SEGMENT
MEM1 DB 11H, 22H; 变量在逻辑段中的位置,表偏移地址(0)
MEM2 DB 'Hello!'; 第二个偏移地址(2)
MEM3 DW 2 DUP(?); DW表示变量类型
DATA ENDS ; DATA 段名/逻辑段地址

MEM1的偏移地址为0,MEM2偏移地址为2,MEM3偏移地址为3

段定义伪指令,无法明确段的属性,需要使用 ASSUME 来明确段性质
有串操作程序中,必须声明附加段
有堆栈操作程序中,必须声明堆栈段

设定段寄存器伪指令

  • 说明所定义逻辑段的性质
  • format:
    • ASSUME 段寄存器名:段名[, 段寄存器名:段名,…]

结束伪指令

  • 表示源程序结束
  • format:
    • END [标号]

过程定义伪指令

  • 用于定义一个过程体

  • format:

    1
    2
    3
    4
    5
    6
    过程名 PROC[NEAR/FAR]
    .
    .
    .
    RET ; 过程体的最后一条指令必须是RET
    过程名 ENDP
  • e.g.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DELAY PROC
    PUSH BX
    PUSH CX
    MOV BL, 2
    NEXT: MOV CX, 4167
    W10M: LOOP W10M
    DEC BL
    JNZ NEXT
    POP CX
    POP BX
    RET
    DELAY ENDP

循环进行了

  • 调用延时子程序: CALL DELAY

宏命令伪指令

  • 宏:

    • 源程序中由汇编程序识别的具有独立功能的一段程序代码
  • 当源程序中需要多次使用同一个程序段时,可以将该程序段定义为一个宏

  • format:

    1
    2
    3
    4
    5
    宏命令名 MACRO <形式参数> --> 通过参数传递方式引用宏
    .
    .
    .
    ENDM
  • e.g.

    1
    2
    3
    4
    5
    DADD  MACRO X, Y, Z
    MOV AX, X
    ADD AX, Y
    MOV Z, AX
    ENDM
  • 宏调用:

    • DADD DATA1, DATA2, SUM
  • 宏展开:

    • MOV AX, DATA1
    • ADD AX, DATA2
    • MOV SUM, AX

调整偏移量伪指令

  • 规定程序或变量在逻辑段中的起始地址

默认情况下,程序或变量在逻辑段中的偏移地址为:0
利用ORG指令,可以改变程序或变量的起始偏移地址

  • format:
    • ORG 表达式 <– 计算值为非负常数
  • e.g.
    1
    2
    3
    4
    DATA SEGMENT
    ORG 1200H
    BUFF DB 1,2; --> 变量BUFF的偏移地址1200H
    DATA ENDS

系统功能调用

调用BIOS功能/DOS功能

DOS/BIOS

  • 驻留在ROM中的基本输入/输出系统
    • 加电自检,装入引导,主要I/O设备处理程序及接口控制
  • DOS
    • 磁盘操作系统

DOS功能/BIOS功能调用是调用系统内核子程序
DOS功能与BIOS功能均通过中断方式调用 –> 调用操作系统内核

无论是调用BIOS还是DOS,都可以简称为 BIOS中断DOS中断

DOS软中断

DOS中断包括:设备管理,目录管理,文件管理,其它用中断类型码区分

DOS软中断:类型码为21H

  • 关于DOS软中断说明:
    • 包括多个子功能的功能包;
    • 各子功能用功能号区分;
    • 用软中断指令调用,中断类型码固定为21H

DOS调用的基本步骤

  • 将调用参数装入指定的寄存器;
  • 将功能号装入AH;
  • 按中断类型好调用DOS中断;
  • 检查返回参数是否正确
  • 调用格式:
    • MOV AH,功能号
    • <置相应参数>
    • INT 21H

单字符输入

  • 调用方法:

    1
    2
    MOV AH, 01
    INT 21H
  • 输入的字符在AL中

  • e.g.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    GET KEY: MOV AH, 1
    INT 21H
    CMP AL, 'Y' ; 输入-> AL
    JZ YES
    CMP AL, 'N'
    JZ NO
    JMP GET KEY
    YES: ...
    NO : ...

字符串输入

  • 接收由键盘输入一串字符
  • 输入的字符串存储在内存指导区域中 –> 字符输入缓冲区
  • 用户自定义缓冲区格式:

image

N1一定要等于缓冲区的大小
N1一定是字节,缓冲区最大只能是255


  • 字符串输入功能号:
    • 10 -> 0AH
  • 缓存区须定义在数据段
  • 方法:
    • AH<–功能号
    • DS:DX<–字符串在内存中的存放地址

这个功能里面,要求将字符串地址赋给 DS:DX

  • e.g.
    1
    2
    3
    4
    5
    6
    7
    DAT1 DB 20, ?, 20 DUP(?);   字符输入缓冲区
    .
    .
    .
    LEA DX, DAT1
    MOV AH, 0AH
    INT 21H

image

单字符显示输出

AH <– 功能号2
DL <– 待输出字符
INT 21H

1
2
3
MOV AH, 2     ; 功能号
MOV DL, 41H
INT 21H ; 执行结果 屏幕显示A

字符串输出显示

  • format:

    • AH <– 功能号09H
    • DS:DX <– 待输出字符串待偏移地址
    • INT 21H
  • NOTE:

    • 被显示的字符串必须以’$’结束;
    • 所显示的内容不应出现非可见的ASCII码;
    • 若考虑输出格式需要,在定义字符串后,加上回车符和换行符。
  • e.g.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DATA  SEGMENT
    MESS1 DB 'Input String:', 0DH, 0AH, '$'
    DATA ENDS
    . ; 0DH -> 回车,出现最后一个字节后一个位置
    . ; 0AH -> 换行
    .
    MOV AH, 09
    MOV DX, OFFSET MESS1
    INT 21H
    .
    .
    .

返回操作系统(DOS)功能

  • 功能号:

    • 4CH
  • 调用格式:

    • MOV AH, 4CH
    • INT 21H
  • func:

    • 程序执行完该2条语句后能正常返回OS
    • 常位于程序结尾处。

HLT用于暂停执行,可能造成程序死机
4CH 能保证正常返回系统

DOS功能调用小节

  • 通过中断指令调用。1个中断类型码对应1个功能程序包;
  • 每个程序包中的子功能通过功能号区分,调用时功能号须送AH;
  • 注意不同于字功能的入口/出口参数要求;

DOS和BIOS中断均可能影响AX