4.2 DOS 系统功能调用和 BIOS 中断调用 概述 磁盘操作系统 DOS 采用模块化 层次化结构, 其层次结构如图所示 2015 年 4 月 13 日星期一 7 时 45 分 11 秒 2

Similar documents
,768 32,767 32K JMP Jnnn (386+) LOOP CALL [Label:] JMP short/near/far address L10: jmp jmp L20: L10 L20

<4D F736F F D20C7B6C8EBCABDCFB5CDB3C9E8BCC6CAA6B0B8C0FDB5BCD1A75FD1F9D5C22E646F63>

untitled

幻灯片 1

(2) Function 0BH: Function 0CH: (pixel, picture element) Function 0DH: Function 0FH: Function 13H:

第四章 8086汇编语言程序设计


Microsoft Word - em78 sub program.doc

微型计算机原理及应用试题 机电96

第5章:汇编语言程序设计

指令系统 可分成如下 6 类 : 数据传送指令 算术运算指令 逻辑运算和移位指令 串操作指令 程序控制指令 处理器控制指令 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 2

第三章 宏汇编语言程序设计

Microsoft PowerPoint - CH3_3.ppt [只读] [兼容模式]

学习MSP430单片机推荐参考书

組譯與連結(Ver6

:23:13 solo estoy( ) 老 师 SIMD 技 术 ALU 同 时 处 理 的 数 据 长 度 只 能 是 ALU 最 大 位 数 的 整 数 分 之 一 对 吗 :25:16 solo estoy( )

Microsoft PowerPoint - C15_LECTURE_NOTE_06

DPJJX1.DOC

Microsoft PowerPoint - C15_LECTURE_NOTE_06

3.3.2 算术运算指令 数据类型 : 无符号和有符号整数 无符号数又分成 : 无符号二进制数 ; 无符号压缩十进制 :1 字节表示 2 个十进制数 ; 无符号非压缩十进制 :1 字节表示 1 个十进制数 有符号数 : 有符号二进制数 用补码表示 2015 年 3 月 26 日星期四 11 时 3

幻灯片 1

Microsoft Word - 实验8_ADDA.doc

数据库系统概论

微机第02章1(指令寻址)

<4D F736F F D20B5DAC8FDCBC4D5C2D7F7D2B5B4F0B0B82E646F63>

<4D F736F F D20CEA2BBFAD4ADC0EDC8EDBCFECAB5D1E9D6B8B5BCCAE92E646F63>

图 内部结构图 8251 的外部引脚如图 所示, 共 28 个引脚, 每个引脚信号的输入输出方式如图中的箭 头方向所示

习 题 一

Microsoft PowerPoint - C15_LECTURE_NOTE_05.ppt

Microsoft PowerPoint - 微原-第3章3.ppt [兼容模式]

数据库系统概论

Microsoft PowerPoint - Ch3-8086CPUæ„⁄令系ç»�(3)-æŁ°æ“®ä¼€é•†æ„⁄令

Microsoft Word - 实验4_IO控制_INT.doc

Ps22Pdf

<4D F736F F F696E74202D DB5DAB0CBBDB22DBBE3B1E0D3EFD1D4B3CCD0F22E >

<4D F736F F F696E74202D BDE1B9B9BBAFB3CCD0F2C9E8BCC D20D1ADBBB7>

主要内容 : 汇编语言源程序的结构汇编语言语句格式伪指令语句功能调用汇编语言程序设计方法宏汇编和条件汇编 2015 年 3 月 30 日星期一 7 时 58 分 57 秒 2

一、填空题

数据库系统概论

目 录

微机原理与接口技术 郭玉洁

(1) 若两个数种有一个是奇数, 则将奇数存入 A 中, 偶数存入 B 中 ; (2) 若两个数均为奇数, 则将两数均加 1 后存回原变量 ; (3) 若两个数均为偶数, 则两个变量均不改变 19. 写一段子程序 SKIPLINES, 完成输出空行的功能 空行的行数由用户在主程序中通过键盘输入, 并

1-1 SH79F6431 A. 2( ) 9~15V ( 12V) U2 U3 3.3V SH79F B. 1(VCC/GND) SH79F6431 C. VDDIO SH79F6431 P4 P5 P0.6 P0.7 VDDIO VDDIO=5V D. 2 V 1.0

Microsoft PowerPoint - C15_LECTURE_NOTE_05.ppt

PowerPoint Presentation

提纲. 1 实验准备. 2 从实模式进入保护模式. 3 小结 陈香兰 ( 中国科学技术大学计算机学院 ) 软件综合实验之操作系统 July 1, / 11

<4D F736F F D20B3E6B4B9A4F930365F32A443AC71C5E3A5DCBEB9B1B1A8EE2E646F63>

《计算概论》课程 第十九讲 C 程序设计语言应用

微處理機期末專題

Microsoft Word - 作业2008.doc

第六章 微型计算机的输入输出

Microsoft PowerPoint - chapter6.ppt

Microsoft PowerPoint - 05-第五讲-寻址方式.pptx

主要内容 指令系统的一般概念 指令操作方式操作码的含义指令对操作数的要求指令执行的结果 寻址方式 指令说明 2015 年 3 月 16 日星期一 8 时 2 分 37 秒 2

Microsoft PowerPoint - os_4.ppt

<4D F736F F F696E74202D D D6B8C1EECFB5CDB DC6E4CBFBD6B8C1EE2E BBCE6C8DDC4A3CABD5D>

标题

3.3.3 逻辑运算和移位指令 1. 逻辑运算指令 运算规则 : 按位操作, 无进 / 借位 对标志位的影响 ( 除 NOT 指令外 ): CF OF SF ZF PF AF 0 0 u 根据运算结果设置 2015 年 3 月 30 日星期一 7 时 57 分 24 秒 2

中北大学

HD61202 HD HD61203 HD61202, HY HY HD61202 HD61202 HD61203 HD =4096 RAMRAM LCD 2HD HD HD /32--

Microsoft PowerPoint - 微原-第3章2.ppt [兼容模式]

7688使用手冊V10.doc

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

CH559指令周期.doc

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

Microsoft Word - P3.doc

Microsoft Word - 選擇_無解答2_.doc

Microsoft Word - ha0013s.doc

CC213

Microsoft PowerPoint - CH3_1.ppt [兼容模式]

1 TPIS TPIS 2 2

今天刚发现的, 比较简单, 于是就来简单分析下吧 该感染样本很简单, 新加了个区段放病毒执行代码, 执行病毒代码, 最后跳回原入口点来执行原文件 下面就是感染后的代码的简单分析 : ; =============== S U B R O U T I N E =====================

四川省普通高等学校

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit

数据库系统概论

MSP430ϵÁе¥Æ¬»úµÄÖ¸Áîϵͳ.pps [¼æÈÝģʽ]

untitled

3.1 num = 3 ch = 'C' 2

12232A LED LED LED EL EL CCFL EL CCF

2 Keil µ vision 2.1 1) Keil µ vision2 V2.34 µ vision3 2) Sino_Keil.exe Keil c:\keil\ 3) JET51 USB PC C:\Keil\ USB PC 4) S-L

1. 介绍 义隆 8 位单片机指令介绍 Application Notes 义隆 8 位单片机指令介绍 EM78/EM88 系列是基于 RISC 的精简指令微控制器, 每条指令是 13 位 15 位, 除 LCALL LJMP MOV R2,A ADD R2,A 改变 PC 指针的指令是 2 个指令

一、单选题(本大题共15小题,每小题1分,共15分)

Microsoft PowerPoint - CH2_1.ppt [兼容模式]

bingdian001.com

F515_CS_Book.book

untitled

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

Microsoft Word - 1.doc

2006年国家公务员招录考试行测真题(A)

Microsoft Word - 《C语言开发入门》课程教学大纲-2.doc

51 C 51 isp 10 C PCB C C C C KEIL

instructions.PDF

CC213

Microsoft Word - 新正文(1-12).doc

学年第二学期校历

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

《C语言程序设计》教材习题参考答案

Transcription:

第 4 章 汇编语言程序设计 (2) 2015 年 4 月 13 日星期一 7 时 45 分 8 秒 1

4.2 DOS 系统功能调用和 BIOS 中断调用 4.2.1 概述 磁盘操作系统 DOS 采用模块化 层次化结构, 其层次结构如图所示 2015 年 4 月 13 日星期一 7 时 45 分 11 秒 2

4.2 DOS 系统功能调用和 BIOS 中断调用 4.2.1 概述 组成 DOS 的各主要模块的功能 : 系统硬件主要指 I/O 设备, 如 CRT 显示器 打印机 键盘 硬盘和鼠标等 基本输入输出系统 BIOS(Basic Input Output System) 包含 : 能直接与底层硬件打交道的设备驱动程序 ; 系统设置信息 ; 开机后自检程序和系统自启动程序 利用中断调用指令 INT n, 可以直接调用 BIOS 中的外设驱动程序, 实现对主要 I/O 设备的控制管理 2015 年 4 月 13 日星期一 7 时 45 分 11 秒 3

4.2 DOS 系统功能调用和 BIOS 中断调用 4.2.1 概述 DOS 核心 MSDOS.SYS 该模块以 BIOS 为基础, 为用户提供一大批可以直接使用的服务程序, 这组服务程序称为 DOS 系统功能调用 可用 INT 21H 指令来调用, 并以功能号来区分不同的服务程序 它们主要用来实现文件管理 存储器管理及设备管理等, 功能比 BIOS 更齐全 更完整 命令处理程序 COMMAND.COM 该模块以可执行命令文件的形式存放在系统盘上, 它执行后便给出 DOS 命令提示符 >, 由它接收用户在此提示符下键入的命令, 进行分析处理后, 让机器执行各种应用程序, 并在 CRT 上显示执行结果 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 4

4.2 DOS 系统功能调用和 BIOS 中断调用 常用软件中断 中断功能调用 由 OS 提供的一组实现特殊功能的子程序供程序员在程序中调用, 以减轻编程工作量 中断功能调用有两种, 一种称为 DOS 功能调用, 另一种称为 BIOS 中断调用 编程时, 不必涉及硬件就可以使用系统的硬件 用户程序在调用这些系统服务程序时, 不是用 CALL 命令, 而是采用软中断指令 INT n 来实现 在 DOS 系统中, 功能调用用软中断指令 INT 21H 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 5

表 DOS 常用软中断命令 软中断功能入口参数出口参数 INT 20H 程序正常退出无 INT 21H 系统功能调用 AH= 功能号 功能调用相应的入口参数 功能调用相应的出口参数 INT 22H 结束退出 不是真正的中断, 特定条件下通过操作系统来发送 INT 23H CTRL-BREAK 退出 在程序装入建立 PSP 时, 该三个中断的中断向量被复制 INT 24H 出错退出 到 PSP 相应偏移位置 INT 25H 读盘 CX= 读出扇区数 DX= 起始逻辑扇区 DS:BX= 缓冲区地址 AL= 盘号 INT 26H 写盘 CX= 写扇区数 DX= 起始逻辑扇区 DS:BX= 缓冲区地址 AL= 盘号 CF=0 成功 CF=1 出错 CF=0 成功 CF=1 出错 INT 27H 驻留退出 DS:DX 程序长度 INT 28-2EH DOS 专用 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 6

4.2.2 DOS 系统功能调用 1. 中断处理程序分类 8086 CPU 可处理 256 类中断, 利用 INT n 指令, 可直接调用 256 个系统已编写好的中断处理程序 INT n 指令中的类型号 n=00~ffh; n=00~04h: 专用中断, 处理除法错 0 单步 1 不可屏蔽中断 NMI 2 断点 3 溢出中断 4; n=10h~1ah 2FH 31H 33H 为 BIOS 中断, 即保存在系统 ROM BIOS 中的 BIOS 功能调用 n=20h~2eh 为 DOS 中断, 应用 DOS 提供的功能程序来控制硬件, 可对显示器 键盘 打印机 串行通信等字符设备提供输入输出服务 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 7

4.2.2 DOS 系统功能调用 1. 中断处理程序分类 例如 : n=20h 为程序结束中断, 利用 INT 20H 中断可返回 DOS 操作系统 n=21h 则为功能最强大的 DOS 中断, 它包含了很多子功能, 给每个子功能程序赋一个编号, 称为功能号, 调用前要送到 AH 寄存器中 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 8

4.2.2 DOS 系统功能调用 2. DOS 系统功能调用方法 系统已将所有子程序按顺序编号, 称为功能调用号 DOS 系统功能调用的步骤 : 1) 功能调用号送到 AH 寄存器中,AH=00~6CH 2) 入口参数送到指定的寄存器中, 一种功能调用又包含多个子功能, 有些调用不带参数 3) 执行 INT 21H 指令 4) 得到出口参数, 或将结果显示在 CRT 上 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 9

4.2.2 DOS 系统功能调用 3. DOS 系统功能调用举例 系统功能调用是微机的磁盘操作系统 DOS 为用户提供的一组例行子程序, 因而又称为 DOS 系统功能调用 INT 2lH 功能大致可以分为如下方面 : 设备管理目录管理文件管理内存分配其它 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 10

表部分键盘和显示 DOS 调用 AH 功能入口参数出口参数 1 键入并显示一个字符 键入字符的 ASCII 码在 AL 中 2 显示一个字符 DL 中置输出字符的 ASCII 码 5 打印机输出一个字符 DL 中置输出字符的 ASCII 码 6 直接控制台 I/O 8 键盘输入一个字符 9 显示字符串 10(0AH) 11(0BH) 键入并显示字符串检验键盘状态 DL=0FFH( 输入 ) DL= 字符 ( 输出 ) DS:DX 置字符串首址, 字符串以 '$' 结束 DS:DX 置字符串首址, 第 1 单元置允许键入的字符数 ( 含一个回车符 ) AL= 输入字符 键入字符的 ASCII 码在 AL 中 键入的实际字符数在第 2 单元中, 键入的字符从第 3 单元开始存放 AL=FFH 有键入 AL=0 无键入 12(0CH) 清除输入缓冲区并请求指定的输入功能 AL= 输入功能号 (1,6,7,8,A) 2015 年 4 月 13 日星期一 7 时 45 分 12 秒 11

1)DOS 键盘功能调用利用 DOS 功能调用, 可将读入的键值送进 AL, 并显示在 CRT 上, 或检查是否有键压下等, 还可将从键盘输入的一串字符输入到内存缓冲区中 2015 年 4 月 13 日星期一 7 时 45 分 13 秒 12

(1) 从键盘输入一个字符 ( 功能号 =1) MOV AH,1 INT 21H <AL 中有键入的字符 > 若有键压下, 读入键值, 并检查是否为 Ctrl-Break 键? 若是, 自动调用 INT 23H 中断, 执行退出命令 ; 否则将键值送入 AL, 并显示该字符 例 DOS 功能调用 1, 等待从键盘输入一个字符 MOVAH,01 H;AH 功能调用号 01H INT 21H ;AL 读入键值, 并显示该字符 2015 年 4 月 13 日星期一 7 时 45 分 13 秒 13

例交互式程序中, 用户键入字母键 Y 或 N, 分别转入不同的程序去处理, 并在 CRT 上显示键入字符 ; 若按了 Ctrl-Break, 则结束程序, 否则继续等待 GET_KEY: MOV AH,01H ;AH 功能调用号 01H INT 21H ;AL 读入键值 CMP AL, Y ; 键值是 Y 吗? JE YES ; 是, 转 YES CMP AL, N ; 不是 Y, 是 N 吗? JE NO ; 是, 转 NO JNE GET_KEY ; 不是 N, 返回继续等待 YES: ; 按 Y 键的处理程序 NO: ; 按 N 键的处理程序 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 14

(2) 控制台 I/O( 功能号 =6) MOV AH,6 ;6 号功能调用 MOV DL,0 FFH;DL=FFH, 键盘输入 INT 21H 当调用时 DL=FFH, 表示从键盘输入字符 执行后, 若 ZF=0, 则 AL 中为输入字符的键值 ; 若 ZF=1, 表示无键压下,AL 中不是键值 如果调用时 DL FFH, 表示从屏幕输出字符 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 15

例 DOS 功能调用 6, 控制台 I/O, 不检查是否按了 Ctrl-Break 键 MOV AH,6 ;6 号功能调用 MOV DL,0 FFH;DL=FFH, 键盘输入 INT 21H 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 16

(3) 输入字符串 ( 功能号 =0AH) 此功能调用从键盘输入一串字符, 并把它存入用户指定的缓冲区中 MOV AH, 0AH LEA DX, < 字符串缓冲区首地址 > INT 21H 用户定义的输入字符串的缓冲区格式 N 1 N 2 ( 预留的 N1 个字节的存储单元 ) 0DH N1: 缓冲区长度 ( 最大键入字符数 ) N2: 实际键入的字符数 ( 不包括回车符 0DH) 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 17

例 4.21 利用 0AH 号 DOS 功能调用, 将键入字符送输入缓冲区 具体过程 : 调用前预先定义一个缓冲区, 首地址为 :DS:DX 缓冲区的第一个字节由用户指定, 存放缓冲区最大容量 ( 字节数 ); 第二个字节保留, 功能调用后存放实际键入的字符个数 ; 从第三个字节开始存入键盘输入的实际字符的 ASCII 码, 直到击了 ENTER 键为止 若键入的字符数小于最大字节数, 缓冲区其余部分都填 0; 若大于最大字节数, 则后键入的字符丢失, 并发出嘟嘟声 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 18

程序如下 : DATA SEGMENT BUFF DB 50 ; 定义缓冲区最大 50(32H) 字节 DB? ; 存实际键入字节数 DB 50 DUP(?) ; 定义 50 个字节空间 ; 存放键入字符的 ASCII 码 DATA ENDS CODE SEGMENT MOV AX,DATA ; 定义 DS:DX MOV DS,AX ;DS= 缓冲区首址基地址 MOV DX,OFFSET BUFF;DX= 缓冲区首址偏址 MOV AH,0AH ;AH= 功能号 10 INT 21H CODE ENDS 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 19

2) 显示功能调用 AH 功能入口参数说明 2 显示一个字符, 检查 Ctrl-Break DL 中置输出字符的 ASCII 码 光标随字符移动 6 直接控制台 I/O, 不检查 Ctrl-Break DL=0FFH( 输入 ) DL= 字符 ( 输出 ) 光标随字符移动 9 显示字符串 DS:DX 置字符串首址 字符串以 '$' 结束, 光标随串移动 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 20

(1) 在显示器上显示一个字符 ( 功能号 =2) MOV AH, 2 MOV DL, < 要显示的字符 > INT 21H 例 : 在显示器上显示一个字符 A MOV AH, 2 MOV DL, A ; 或 MOV DL, 41H INT 21H 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 21

(2) 显示字符串 ( 功能号 =9) MOV AH, 9 LEA DX, < 字符串 > INT 21H 注意 : 字符串的首地址送到 DS:DX, 被显示的字符串必须以 $ 结束 2015 年 4 月 13 日星期一 7 时 45 分 15 秒 22

例 : 在屏幕上显示 : HELLO,WORLD! ; 在数据段定义字符串 : DATA SEGMENT STR1 DB HELLO,WORLD!$ DATA ENDS ; 在代码段中进行显示输出 MOV AX,DATA MOV DS,AX;DS 字符串起始段地址 MOV AH,9 LEA DX,STR1;DX 偏移地址 INT 21H 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 23

3) 打印功能调用 将要在打印机上打印的字符的 ASCII 码送到 DL 中, 作为入口参数, 然后执行 5 号功能调用,DL 中的字符便会送到打印机去打印 例 4.24 在打印机上打印一串字符 Robot, 打印前换页, 打印完后回车 换行 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 24

3) 打印功能调用 程序如下 : CHAR DB 0CH, Robot, 0DH, 0AH, $ ; 待打印字符串,0AH 为换行码 MOV BX,0 ;BX 指向字符串开头 MOV AH,5 ;AH= 功能号 5 NEXT: MOV DL,CHAR [BX] ; 取一个字符 CMP DL, $ ; 是 $ 符吗 JE TO_STOP ; 是, 转停止打印 INT 21H ; 否, 打印该字符 INC BX ; 指向下一个字符 JMP NEXT ; 继续打印下一个字符 TO_STOP: ; 停止打印处理 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 25

4) 日期与时间设置 AH 功能入口参数出口参数 2BH 2AH 2DH 2CH 设置日期 取得日期 设置时间 取得时间 CX: 年号 DH: 月号 DL: 日号 CH: 小时 CL: 分 DH: 秒 DL: 百分之一秒 AL=0, 成功 AL=0FFH, 无效 CX: 年号 DH: 月号 DL: 日号 CH: 小时 CL: 分 DH: 秒 DL: 百分之一秒 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 26

(1) 设置日期 例设置日期为 2013 年 4 月 9 日 MOV CX,2013 ; 年份 MOV DH,4 ; 月份 MOV DL,9 ; 日期 MOV AH,2BH INT 21H 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 27

(2) 取得日期格式为 : MOV AH,2AH INT 21H 执行结果 : CX= 年份 DH= 月份 DL= 日期二进制方式存放 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 28

(3) 设置时间 例设置时间为 12 点 3 分 12.34 秒 MOV CH,12; 时 MOV CL,3; 分 MOV DH,12; 秒 MOV DL,34; 百分秒 MOV AH,2DH INT 21H 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 29

(4) 取得时间格式为 : MOV AH,2CH INT 21H 执行结果 : CH= 时 CL= 分 DH= 秒 DL= 百分秒二进制存放 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 30

5) 返回操作系统 格式为 : MOV AH,4CH INT 21H 执行结果 : 返回操作系统, 出现提示符 如 : C:\> C:\DOS> 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 31

4.2.3 BIOS 中断调用 BIOS: 基本输入输出系统, 是固化在 EPROM (EEPROM FLASH) 存储器 0FE000H 开始的 8KB 中的一组实现基本输入输出功能的子程序 BIOS 主要功能包括 : (1) 驱动系统中所配置的常用外设 ( 即驱动程序 ), 如显示器 键盘 打印机 磁盘驱动器 通信接口等 (2) 开机自检, 引导装入 (3) 提供时间 内存容量及设备配置情况等参数 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 32

4.2.3 BIOS 中断调用 说明 : 有些 DOS 系统功能调用和 BIOS 中断调用能完成同样的功能 例如, 要打印一个字符, 可以用 INT 21H 的 5 号 DOS 功能调用, 也可用 BIOS 的 INT 17H 的 0 号中断调用 由于 BIOS 更接近硬件, 使用起来要复杂一些, 尽量使用 DOS 系统功能调用 有些情况下, 必须使用 BIOS 中断调用 例如, INT 17 中断的 2 号调用为读打印机状态,DOS 功能调用无这种功能, 只能使用 BIOS 中断调用 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 33

4.2.3 BIOS 中断调用 BIOS 中断调用与 DOS 系统功能调用类似, 用户无须了解相关设备的结构与组成细节, 直接调用 BIOS 调用通过多个软中断提供, 调用方法为 : MOV AH,< 功能号 >; 多子功能时 < 设置入口参数, 一般将参数放在寄存器中 > INT n< 中断类型号 > 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 34

BIOS 中的几个主要中断类型如下 : INT 00H 0 作除数 INT 01H 单步中断 INT 02H 非屏蔽中断 (NMI) INT 03H 断点中断 INT 04H 算术溢出错误 INT 05H 打印屏幕和 BOUND 越界 INT 06H 非法指令错误 INT 07H 处理器扩展无效 INT 08H 时钟中断 INT 09H 键盘输入 INT 0BH 通信口 (COM2:) INT 0CH 通信口 (COM1:) INT 0EH 磁盘驱动器输入 / 输出 2015 年 4 月 13 日星期一 7 时 45 分 16 秒 35

BIOS 中的几个主要中断类型如下 ( 续 ): INT 11H 读取设备配置 INT 12H 读取常规内存大小 ( 返回值 AX 为内存容量, 以 K 为单位 ) INT 16H 键盘中断调用 INT 18H ROM BASIC INT 19H 重启动系统 INT 1BH CTRL+BREAK 处理程序 INT 1CH 用户时钟服务 INT 1DH 指向显示器参数表指针 INT 1EH 指向磁盘驱动器参数表指针 INT 1FH 指向图形字符模式表指针每类中断由包含许多子功能, 调用时通过功能号指定 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 36

1. 键盘 I/O 中断调用 (INT 16H) 键盘 I/O 中断调用有三个功能, 功能号为 0, 1, 2, 且必须把功能号放在 AH 中 1)0 号功能调用格式 : MOV AH, 0 INT 16H 功能 : 从键盘读入字符送 AL 寄存器 执行时, 等待键盘输入, 一旦输入, 字符的 ASCII 码放入 AL 中 若 AL=0, 则 AH 为输入的扩展码 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 37

1. 键盘 I/O 中断调用 (INT 16H) 2)1 号功能调用格式 : MOV AH, 01H INT 16H 功能 : 用来查询键盘缓冲区, 对键盘扫描但不等待, 并设置 ZF 标志 若有按键操作 ( 即键盘缓冲区不空 ), 则 ZF=0,AL 中存放的是输入的 ASCII 码,AH 中存放输入字符的扩展码 若无键按下, 则标志位 ZF=1 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 38

1. 键盘 I/O 中断调用 (INT 16H) 3)2 号功能调用格式 : MOV AH, 02H INT 16H 功能 : 检查键盘上各特殊功能键的状态 执行后, 各种特殊功能键的状态放入 AL 寄存器中 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 39

例检查 Ctrl 键是否按下, 若按下, 则控制转移到某个程序段执行 MOV AH, 02H INT 16H ; 取键盘状态到 AL 中 AND AL, 0000 0100B ; 检查 Ctrl 键是否按下 JNZ CTRL-ON... CTRL-ON: 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 40

2. 打印机 I/O 中断调用 (INT 17H) 打印机 I/O 中断调用有三个功能, 功能号为 0, 1, 2 1)0 号功能调用入口参数为 AL 中放入字符的 ASCII 码,DX 中放打印机号 (0~2) 打印字符 'A' 的调用格式 : MOV AL, 'A' MOV DX, 01H MOV AH, 0 INT 17H 功能 : 打印一个字符, 且返回打印机状态到 AH 中 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 41

2)1 号功能调用格式 : MOV AH, 01H INT 17H 功能 : 初始化打印机, 并返回打印机状态到 AH 中 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 42

3)2 号功能调用格式 : MOV AH, 02H INT 17H 功能 : 返回打印机状态到 AH 中 0~2 号调用返回的打印机状态字 : 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 43

3. 显示中断 (INT 10H) 的功能调用 控制系统中的视频显示, 也称视频服务中断 视频 ROM BIOS 位于显卡上, 不同显卡能提供的视频服务功能不一样,INT 10H 支持多种服务功能, 由 AH 指定,AH=00H~1CH INT 10H 中断控制显示器的功能十分强大, 还在不断发展 采用汇编语言控制很复杂, 程序也较长, 一般采用高级语言编程 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 44

3. 显示中断 (INT 10H) 的功能调用 00H 设置显示器模式 01H 设置光标形状 02H 设置光标位置 03H 读取光标信息 04H 读取光笔位置 05H 设置显示页 06H 07H 初始化或滚屏 08H 读光标处的字符及其属性 09H 在光标处按指定属性显示字符 0AH 在当前光标处显示字符 0BH 设置调色板 背景色或边框 2015 年 4 月 13 日星期一 7 时 45 分 17 秒 45

3. 显示中断 (INT 10H) 的功能调用 ( 续 ) 0CH 写图形象素 0DH 读图形象素 0EH 在 Teletype 模式下显示字符 0FH 读取显示器模式 10H 颜色中断 11H 字体中断 12H 显示器的配置中断 13H 在 Teletype 模式下显示字符串 1AH 读取 / 设置显示组合编码 1BH 读取功能 / 状态信息 1CH 保存 / 恢复显示器状态 2015 年 4 月 13 日星期一 7 时 45 分 18 秒 46

3. 显示中断 (INT 10H) 的功能调用应用例 : 把一个 笑脸 图案在屏幕上斜线移动 具体要求 : (1) 设置屏幕属性并清屏, 置光标初始位置坐标 ; (2) 在指定坐标位置显示 ; (3) 延时一段时间 ; (4) 清除屏幕 ; (5) 行列坐标各加 1, 返回第二步 2015 年 4 月 13 日星期一 7 时 45 分 18 秒 47

3. 显示中断 (INT 10H) 的功能调用 流程图 2015 年 4 月 13 日星期一 7 时 45 分 18 秒 48

3. 显示中断 (INT 10H) 的功能调用 清屏子程序 CLR PROC PUSH PUSH PUSH PUSH MOV AX BX CX DX AL,0 MOV AH,6 ; 清屏功能号 MOV CH,10 ; 起始行号 MOV CL,10 ; 起始列号 MOV DH,69 ; 结束行号 MOV DL,69 ; 结束列号 MOV BH,70H ; 该区域屏幕属性 : 白底黑字 INT 10H ; 调用该中断 POP DX POP CX POP BX POP AX RET CLR ENDP 该子程序执行后, 使得屏幕上 (10,10) 到 (69,69) 这一区域被清屏, 同时设置该区域的显示属性为白底黑字 2015 年 4 月 13 日星期一 7 时 45 分 19 秒 49

3. 显示中断 (INT 10H) 的功能调用 延时子程序 DELAY PROC PUSH CX PUSH DX MOV DX,6000 L1: MOV CX,28000 L2: LOOP L2 DEC DX JNZ L1 POP DX POP CX RET DELAY ENDP 双重循环实现的延时子程序, 外层循环由 DX 控制次数 ; 内层循环由 CX 控制次数 2015 年 4 月 13 日星期一 7 时 45 分 19 秒 50

3. 显示中断 (INT 10H) 的功能调用 主程序 STACK SEGMENT STK DB 100 DUP(?) TOP EQU LENGTH STK STACK ENDS CODE SEGMENT ASSUME CS:CODE,SS:STACK START: MOV AX,STACK MOV SS,AX MOV AX,TOP MOV SP,AX CALL CLR MOV DH,10 MOV DL,10 ; 光标初始位置 DIS: MOV BH,0 MOV AH,2 INT 10H ; 置光标 MOV AL,2 ; 的 ASCII 码 MOV BL,70H MOV CX,1 MOV AH,0AH INT 10H ; 在光标位置显示字符 CALL DELAY CMP DH,69 JE OVER ; 是否显示结束 CALL CLR INC DH INC DL JMP DIS ; 光标下移 OVER: CALL CLR MOV AH,4CH INT 21H CODE ENDS END START 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 51

4. 时间设置和读取 (INT 1AH) 00H 读取时钟 01H 设置时钟 02H 读取时间 03H 设置时间 04H 读取日期 05H 设置日期 06H 设置闹钟 07H 闹钟复位 0AH 读取天数计数 0BH 设置天数计数 80H 设置声音源信息 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 52

5. 鼠标中断功能调用 INT 33H 提供对鼠标 (mouse) 的控制和调整, 处理鼠标驱动程序提供的信息 功能号为 00H~34H 与 DOS 系统功能调和大部分 BIOS 功能调用不同, 功能号不放入 AH, 而放在 AL 中, 事先令 AH=0 可用的鼠标功能调用有 50 余个 如 : 复位, 显示或隐藏光标, 设置光标位置, 设置图形或文本光标, 设置或获取加速曲线等等 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 53

4.3 汇编语言程序设计方法与实例 概述 1. 程序质量 模块化 易读 程序流程简洁 逻辑关系正确 代码效率高, 加注释 2. 汇编语言程序设计的步骤 : 1 根据实际问题抽象出数学模型, 确定算法 ; 2 画出程序框图 ( 流程图 ) ; 3 分配内存工作单元和寄存器 ; 4 根据框图编写源程序, 生成.ASM 文件 ; 5 对源程序汇编, 生成.OBJ 目标文件 ; 6 将.OBJ 文件连接成.EXE 执行文件 ; 7 运行 调试 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 54

4.3 汇编语言程序设计方法与实例 3. 汇编语言程序设计方法 每个程序只有一个入口, 必须要有出口, 中间内容不能含有死循环语句 程序都按照顺序结构 条件分支结构和循环结构等 3 种基本结构进行构建 设计时先考虑总体 全局目标, 再考虑细节 局部问题, 把复杂问题分解为一个个模块或子目标, 一步步进行设计 将这些基本结构 子模块合理组合起来, 就可构成一个大的程序 编程时要在程序行上适当加注释 这样设计出来的程序层次分明, 结构清楚, 可读性强, 便于调试 编写较复杂的程序时, 一般应先画出程序流程图, 将设计步骤细化, 再按流程图设计编写程序 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 55

汇编语言上机过程 Y Y 开始输入 ( 修改 ) 源程序 汇编有错? N 连接有错? N 运行有错? Y 查错 N 用 EDIT,NOTEPAD 等任何文本编辑器 源程序存为.ASM 文件 用 UltraEdit MASM 宏汇编程序进行汇编 生成.OBJ 目标文件 命令格式 :MASM < 源文件名.ASM> 用 LINK 连接程序进行连接 连接后生成.EXE 可执行文件 命令格式 :LINK < 目标文件名.OBJ>; 结束 用 TD DEBUG 等调试程序进行调试 命令格式 :TD < 可执行文件名.EXE> 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 56

4.3.1 顺序结构程序设计 顺序结构程序也称为简单程序, 这种程序按指令排列的先后顺序逐条执行 2015 年 4 月 13 日星期一 7 时 45 分 20 秒 57

例两个 32 位无符号数乘法程序 在 8086 中, 数据是 16 位的, 它只有 16 位运算指令, 若是两个 32 位数相乘就无法直接用指令实现 ( 在 80386 中有 32 位数相乘的指令 ), 但可以用 16 位乘法指令做 4 次乘法, 然后把部分积相加来实现 若数据区中已有一个缓冲区存放了 32 位的被乘数和乘数, 保留了 64 位的空间以存放乘积, 能实现上述运算的程序流程图如图所示 2015 年 4 月 13 日星期一 7 时 45 分 21 秒 58

程序 name 32 bit multiply data segment mulnum dw 0000,0ffffh,0000, 0ffffh,4 dup(?) data ends stack segment para stack stack db 100 dup(?) stack ends code segment assume cs:code,ds:data,ss:stack,es:data start proc far begin: push ds ;DS 中包含的是程序段前缀的起始地址 mov ax,0 push ax ; 设置返回至 DOS 的段值和 IP 值 mov ax,data mov ds,ax mov es,ax ; 置段寄存器初值 lea bx,mulnum 2015 年 4 月 13 日星期一 7 时 45 分 21 秒 59

程序 mulu32: mov ax,[bx] ;B AX mov si,[bx+4] ;D SI mov di,[bx+6] ;C DI mul si ;B D mov [bx+8],ax ; 保存部分积 1 mov [bx+0ah],dx mov ax,[bx+2] ;A AX mul si ;A D add ax,[bx+0ah] adc dx,0 ; 部分积 2 的一部分与部分积 1 的相应部分相加 mov [bx+0ah],ax mov [bx+0ch],dx ; 保存 mov ax,bx] ;B AX mul di ;B C add ax,[bx+0ah] ; 与部分积 3 的相应部分相加 adc dx,[bx+0ch] 2015 年 4 月 13 日星期一 7 时 45 分 21 秒 60

程序 start code end mov mov pushf mov mul popf adc adc mov mov ret endp ends begin [bx+0ah],ax [bx+0ch],dx ; 保存后一次相加的进位位 ax,[bx+2];a AX di;a C ax,[bx+0ch]; 与部分积 4 的相应部分相加 dx,0 [bx+0ch],ax [bx+0eh],dx 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 61

例 4.34 由人机对话从键盘输入 1 个 10 进制数 (0~9), 查表求键入数字的平方值, 存入 AL 寄存器中, 并显示有关的提示信息 试编写汇编语言程序 解 : 数据段中, 先给出数字 0~9 的平方值, 逐个存入 TABLE 开始的内存中, 形成表格, 以便查找, 再给出等待显示的提示信息 代码段由 3 个部分组成 : 显示提示信息 ; 等待键入数字 ; 查表求键入数字的平方值, 并将结果存入 AL 中 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 62

程序如下 : DATA SEGMENT TABLE DB 0, 1, 4, 9, 16, 25, 36, 49, 64, 81; 数字 0~9 的平方值 BUF DB Please input a number(0~9):,0dh,0ah, $ ; 提示信息 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX ; 设置 DS MOV DX,OFFSET BUF ; 设置 DX, 使字符串首地址 =DS:DX MOV AH,9H ;9 号 DOS 功能调用 INT 21H ; 显示提示信息 MOV AH,01 ;1 号功能调用, 等待键入字符 INT 21H ;AL 键入数字的 ASCII 码 AND AL,0FH ;AL 截下数字值 ;( 表内元素序号 ) MOV BX,OFFSET TABLE ;BX 指向表头地址 TABLE MOV AH,0 ;AX 寄存器高字节清 0 ADD BX,AX ; 表头地址 + 键入数字 (AL), 结果存入 BX MOV AL,[BX] ; 查表求得平方值 ; MOV AX,4C00H INT 21H ; 返回 DOS CODE ENDS END START 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 63

例 4.35 在存储单元 A1 和 A2 中, 各存有一个 2 字节的无符号数, 低字节在前, 高字节在后 编程将两数相加, 结果存入 SUM 单元, 也要求低字节在前, 高字节在后, 进位存入最后一个字节单元 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 64

程序如下 : DATA SEGMENT A1 DB 56H,78H ; 数 A1 A2 DB 4FH,9AH ; 数 A2 SUM DB 3 DUP(0) ; 存两数相加之和, 考虑进位位 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA BEGIN: MOV AX,DATA MOV DS,AX ; 设置数据段基址 MOV BX,0 ;BX 为地址指针, 初值清 0 CLC ; 进位位清 0 MOV AL,A1 [BX] ; 取低字节 A1 ADC AL,A2 [BX] ; 与 A2 低字节相加 MOV SUM [BX],AL ; 存入 SUM 单元 ( 低字节 ) INC BX ; 调整指针 MOV AL,A1 [BX] ; 取高字节相加 ADC AL,A2 [BX] MOV SUM [BX],AL ; 存高字节 JNC STOP ; 无进位, 转 STOP INC BX ; 有进位 MOV AL,0 INC AL MOV SUM [BX],AL ; 进位存入 SUM+2 单元 STOP: MOV AX,4C00H INT 21H CODE ENDS END BEGIN 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 65

4.3.2 分支结构 要求程序根据不同条件选择不同的处理方法, 即程序处理步骤中出现了分支, 应根据某一特定条件, 选择其中一个分支执行 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 66

4.3.2 分支结构 1. 分支结构 (IF THEN 结构 ) 条件满足? 标号 : Y 处理体 N 程序结构 : 测试 / 比较指令 (TEST/CMP) 条件转移指令 (Jx 标号 ) 处理体 标号 : 其他指令 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 67

2. 多分支 (IF THEN ELSE 结构 ) 程序结构 : 条件 1 条件 2 条件满足? 标号 1: TEST/CMP 指令 Jx 标号 1 处理体 P1 处理 P1 标号 2: 处理 P2 JMP 标号 2 标号 1: 处理体 P2 标号 2: 其他指令 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 68

2. 多分支 (IF THEN ELSE 结构 ) 例 4.36 设某学生的英语成绩已存放在 AL 寄存器中, 如果分数低于 60 分, 则打印 F, 如高于等于 85 分, 则打印 G, 否则打印 P 这就是一个分支程序 2015 年 4 月 13 日星期一 7 时 45 分 22 秒 69

3.CASE 结构程序结构 : 标号 1: 标号 2: 标号 n: 标号 n+1: Y? P1 条件 1 成立 N 条件 2 成立? 条件 n 成立? Pn+1 N N Y Y P2 Pn TEST/CMP 指令 ( 测试条件 1) Jx 标号 1 ; 不满足转标号 1 处理体 P1 JMP 标号 n+1 标号 1:TEST/CMP 指令 ( 测试条件 2) Jx 标号 2 ; 不满足转标号 2 处理体 P2 JMP 标号 n+1 标号 2:TEST/CMP 指令 ( 测试条件 3) Jx 标号 3 ; 不满足转标号 3 处理体 P3 JMP 标号 n+1 标号 3:TEST/CMP 指令 ( 测试条件 4) 标号 n+1:( 公共出口 ) 2015 年 4 月 13 日星期一 7 时 45 分 23 秒 70

3.CASE 结构 例 4.37 在存储器中以首地址 BUF 开始存有一串字符, 字符串个数用 COUNT 表示 要求统计数字 0~9 字母 A~Z 和其它字符的个数, 并分别将它们的个数存储到 NUM 开始的 3 个内存单元中去 在 ASCII 码表中, 数字 0~9 的 ASCII 码为 30H~39H, 大写字母 A~Z 的 ASCII 码为 41H~5AH, 其余值为其它字符或控制符的 ASCII 码值 可以将 ASCII 码分成 5 个部分或 5 个分支来处理, 其示意图如下 2015 年 4 月 13 日星期一 7 时 45 分 23 秒 71

3.CASE 结构 先从 BUF 单元取出 1 个字符的 ASCII 码, 经分支程序判断它属于数字 字母还是其它字符, 然后使相应计数器的值 +1 数字个数存放在 DL 中, 字母个数存放在 DH 中 接下来分析第 2 个数, 直至所有字符处理完后, 将统计出的个数送入相应存储单元 2015 年 4 月 13 日星期一 7 时 45 分 23 秒 72

程序如下 : DATA SEGMENT BUF DB +36, PRINT, abc, 2A0CH, # ; 一串字符 COUNT EQU $-BUF ;COUNT= 字符总个数 NUM DB 3 DUP(?) ; 先后存放存数字 字母 ; 和其它字符个数 DATA ENDS ; CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX ; 设置数据段 MOV CH,COUNT ;CH 数组长度 MOV BX,0 ;BX 为基址指针, 初值清 0 MOV DX,0 ;DH 数字个数,DL 字母个数, 初值清 0 LOOP1: MOV AH,BUF [BX] ;AH 取一个数 CMP AH,30H ;<30H? JL NEXT ;1 是, 转 CMP AH,39H ;>39H? JG ABC ; 是, 转 INC DH ;2 否, 数字个数增 1 JMP NEXT 2015 年 4 月 13 日星期一 7 时 45 分 23 秒 73

程序如下 : ABC: CMP AH,41H ;<41H? JL NEXT ;3 是, 非字母, 转 CMP AH,5AH ;>5AH? JG NEXT ;5 是, 非字母, 转 INC DL ;4 否, 字母个数增 1 NEXT: INC BX ; 基地址指针加 1 DEC CH ; 字符串长度减 1 JNZ LOOP1 ; 未完, 取下一个数 CODE END MOV NUM,DH ; 已完, 存数字个数 MOV NUM+1,DL ; 存字母个数 MOV AH,COUNT SUB AH,DH SUB AH,DL ; 计算出其它字符个数 MOV NUM+2,AH ; 存其它字符个数 MOV AX,4C00H INT 21H ENDS START 2015 年 4 月 13 日星期一 7 时 45 分 23 秒 74

4. 跳转表实现多分支 BASE BASE+2 P1 P2 P1 低位 P1 高位 P2 低位 P2 高位 BASE E9 P1 低位 P1 高位 E9 P2 低位 P2 高位 BASE JMP P1 JMP P2 31 32 38 关键字值 P1 程序入口地址 P2 程序入口地址 P8 程序入口地址 根据表内地址分支根据表内指令分支根据关键字分支 2015 年 4 月 13 日星期一 7 时 45 分 23 秒 75

例根据表内指令分支 DATA SEGMENT BASE DB E9,P1 低,P1 高,E9 DB E9 E9,P9 低,P9 高 DATA ENDS MOV AH,1 INT 21H; 键入字符存 AL AND AL,0FH MOV AH,0 MOV BL,AL; ADD AL,AL; ADD AL,BL; 将输入的数字乘 3 MOV BX,OFFSET BASE ADD BX,AX; 得到跳转表的偏移地址 JMP BX; 跳转表中存放另一条跳转指令 BASE E9 P1 低位 P1 高位 E9 P2 低位 P2 高位 JMP P1 JMP P2 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 76

4.3.3 循环程序结构 1.D0 UNTIL< 条件 > 结构先执行, 再判断条件 工作部分至少执行一次 初始化 循环体 修改控制参数 循环控制? Y N 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 77

2. DO WHILE< 条件 > 结构先判断条件, 再执行 工作部分有可能一次都不执行 初始化 循环控制? Y 循环体 N 出口 修改控制参数 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 78

3. 多重循环在一个循环中包含另一个循环, 这就是多重循环 如, 多维数组的运算 注意 : 1 各循环的初始控制条件及程序实现 ; 2 循环可以嵌套 ( 多重循环 ), 但多个循环体之间不能交叉, 控制条件不能混淆 ; 防止出现死循环, 即不能让循环回到初始条件而引起死循环 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 79

例 4.38 在一串给定个数的数据中寻找最大值, 存放到 MAX 存储单元中 DATA SEGMENT BUF DW 1234H,3200H,4832H,5600H ; 一串字数据 COUNT EQU ($-BUF)/2 ; 数据个数 ( 循环次数 ) MAX DW? ; 存最大值 DATA ENDS ; STACK SEGMENT STACK STAPN DB 100 DUP(?) TOP EQU LENGTH STAPN STACK ENDS 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 80

CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE,SS:STACK START: MOV AX,STACK MOV SS,AX MOV SP,TOP PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX MOV CX,COUNT ;CX 字符个数 LEA BX,BUF ;BX BUF 的偏移地址 MOV AX,[BX] ;AX 缓冲器中取一个数 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 81

INC BX ; 修改地址指针 INC BX DEC CX ; 循环次数减 1 AGAIN:CMP AX,[BX] ;AX 与后取的数比较 JGE NEXT ; 如 AX 中数大于等于后者, 则转 MOV AX,[BX] ; 如后取的数大, 则将其送 AX NEXT:LOOP AGAIN ; 没处理完, 转 ( 循环操作 ) RET ; 返回 DOS MAIN ENDP ; 处理完, 结束 CODE ENDS END MAIN 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 82

例 : 编写程序, 在 S 中存放 100 个数, 要求设计程序将这些数由小到大排序, 排序后的数, 仍放在该区域中, 并显示排序后的结果 DATA SEGMENT STR1 DB 'PLEASE INPUT SOME DATA,THE END FLAG IS$','$' S DB 100 DB? DB 100 DUP(?) DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX LEA DX,STR1 MOV AH,9 INT 21H ; 显示 STR1 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 83

MOV DL,0AH MOV AH,2 INT 21H ; 显示 DL 中的单个字符 0AH( 换行 ) LEA DX,S MOV AH,0AH INT 21H ; 输入字符串到缓冲区 S 中 MOV SI,DX ; 缓冲区首址送 SI MOV DL,0AH MOV AH,2 INT 21H ; 显示 DL 中的单个字符 0AH( 换行 ) MOV CL,[SI+1] MOV CH,0 SUB CX,2 MOV DX,CX DEC DX ADD SI,2 L1: MOV BL,[SI] INC SI 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 84

MOV BH,[SI] CMP BH,BL JG L2 MOV [SI],BL MOV [SI-1],BH L2: LOOP L1 LEA SI,S ADD SI,2 MOV CX,DX DEC DX JNZ L1 LEA DX,S ADD DX,2 MOV AH,9 INT 21H MOV AH,4CH INT 21H CODE ENDS END START 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 85

循环程序, 课堂练习 计算两个多字节十六进制数之和 : 3B74AC60F8H+20D59E36C1H=? 提示 : 这是一个单循环程序式中被加数和加数均有 5 个字节, 可以编一个循环程序实现以上运算 假设已将被加数和加数分别存入从 DATA1 和 DATA2 开始的两个内存区, 且均为低位字节在前, 高位字节在后, 如图 要求相加所得结果仍存回以 DATA1 为首址的内存区 2015 年 4 月 13 日星期一 7 时 45 分 24 秒 86

程序如下 : MOV CX, 5 ; 设置循环次数 MOV SI, 0 ; 置位移量初值 CLC ; 清进位 CF LAD: MOV AL, DATA2[SI] ; 取一个加数 ADC DATA1[SI], AL ; 和一个被加数相加 INC SI ; 位移量加 1 DEC CX ; 循环次数减 1 JNZ LAD ; 加完否, 若没完, 转 LOOPER, 继续相加 HLT ; 程序暂停 2015 年 4 月 13 日星期一 7 时 45 分 25 秒 87

4.3.4 代码转换程序 在计算机中, 经常需要将数据从一种形式转换成另一种形式 例如, 2 进制数转换成 10 进制数, 再转换成 ASCII 码显示出来 ; 10 进制数转换成 2 进制数, 再转换成 16 进制数等 要编写各种代码转换程序 2015 年 4 月 13 日星期一 7 时 45 分 25 秒 88

4.3.4 代码转换程序 例 4.41 将 AL 寄存器中的二进制数转换成非压缩 BCD 数, 存入 AX 中, 再转换成 ASCII 码后在 CRT 上显示 设 AL 中的初值为 01100010B=62H, 它等于 10 进制数的 98 将它除以 10 后, 可得商为 9, 余数为 8, 将其存放入 AX 中, 使 AX=0908H, 与 3030H 相加 ( 也可相或 ), 即转换成 ASCII 码 3938H, 用 2 号 DOS 功能调用即可显示出来 2015 年 4 月 13 日星期一 7 时 45 分 25 秒 89

4.3.4 代码转换程序 BIN_ASC PROC NEAR MOV AH,0 MOV BL,10 ; 除数 DIV BL ;AL 商 (9), AH 余数 (8) XCHG AH,AL ; AX=0908H( 非压缩 BCD 数 ) ADD AX,3030H ;AX=3938H( 转换为 ASCII 码 ) MOV CX,AX ;CX 3938H MOV DL,CH MOV AH,2 INT 21H ; 显示 DL 中的 9 MOV DL,CL MOV AH,2 INT 21H ; 显示 DL 中的 8 RET BIN_ASC ENDP 2015 年 4 月 13 日星期一 7 时 45 分 25 秒 90

综合举例 十 二进制数 ASCII 码之间的互相转换 1 BCD 数 2 进制数算法 :D n-1 *10 n-1 + +D 0 *10 0 = ( (D n-1 *10+ D n-2 )*10+ )*10+ D 0 = ( ((0*10+D n-1 )*10+ D n-2 )*10+ )*10+ D 0 即 : 新的中间结果 = 中间结果 *10+ 本位数字 ( 中间结果初值为 0) 2015 年 4 月 13 日星期一 7 时 45 分 25 秒 91

程序 1 将 65535 的非压缩 BCD 数转换成 2 进制数 程序如下 : ; 数据段定义 data SEGMENT decnum DB 5, 3, 0, 1, 9 ;BCD 数 53019 binnum DW? data ENDS 2015 年 4 月 13 日星期一 7 时 45 分 25 秒 92

prog SEGMENT ASSUME CS:prog,DS:data begin: MOV AX, data MOV DS, AX MOV SI, OFFSET decnum MOV CX, 5 ;5 位 BCD 数 MOV BX, 10 XOR AX, AX ; 中间结果初始值为 0 next: MUL BX ; 中间结果 *10+ 本位数字 ADD AL, [SI] ADC AH, 0 ; 将大于 255 的进位加到高字节 INC SI ; 指向下位 BCD 数 LOOP next MOV binnum, AX ; 保存结果 MOV AH, 4CH INT 21H prog ENDS END begin 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 93

程序 2 把 255 的非压缩 BCD 数转换成 2 进制数 decnum DB 1,5,9 ;BCD 数 159 binnum DB? MOV AX,decnum XCHG AH, AL ; 百位在 AH, 十位在 AL AAD ; 百位数 *10 + 十位数 MOV AH, AL ; 中间结果送 AH MOV AL, decnum+2 AAD ; 中间结果 *10 + 个位数 MOV binnum, AL 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 94

2 ASCII 码数字 二进制数 ( 用于输入 ) 例 : 从键盘输入两个整数, 并求其和 因键入为整数, 故要进行如下转换 : ASCII BCD 二进制数 ASCII BCD 码很简单, 高 4 位清零即可得到非压缩的 BCD 码 BCD 二进制数, 在本例 ( 以及前例 1) 中采用以下方法 : ((((0+ 千位数 )*10+ 百位数 )*10)+ 十位数 )*10+ 个位数 第一次中间结果 第二次中间结果 第三次中间结果 最终结果 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 95

主程序 开始 转换子程序 开始 键入两个数 两个数分别转换成二进制数 相加 如有溢出则提示 返回 DOS 取第一个 ASCII 码 N 是负号吗? Y 数字符个数 -1, 指针 +1 指针定位 字符个数 -1 Y = 0? N 取数字, 与中间结果相加, 再乘以 10 加个位数 是负数则求补 结束 指向下一个数字字符存结果 结束 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 96

程序如下 : DATA SEGMENT STR1 DB 10,?,10 DUP(?) ; 第 1 个数的输入缓冲区 STR2 DB 10,?,10 DUP(?) ; 第 2 个数的输入缓冲区 NUM DW?,? ; 存转换后的二进制数 SUM DW 0 ; 存和 OVER DB Overflow!,13,10, $ DATA ENDS ; CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 97

START: MOV AX,DATA MOV DS,AX MOV AH,0AH LEA DX,STR1 INT 21H ; 输入第一个数字串 ( 设为 26) MOV AH,0AH LEA DX,STR2 INT 21H ; 输入第二个数字串 ( 设为 33) LEA BX,STR1 ; 串 1 的首地址送 BX LEA DI,NUM ; 串 1 二进制结果首地址送 DI CALL CHANGE ; 将串 1 ASCII 码 二进制 LEA BX,STR2 ; 串 2 的首地址送 BX 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 98

NEXT: MAIN LEA DI,NUM+2 ; 串 2 二进制结果首地址送 DI CALL CHANGE ; 将串 2 ASCII 码 二进制 MOV AX,NUM ;(AX)=[NUM]=001AH( 串 1) ADD AX,NUM+2 ; 两数相加,(AX)=003BH( 串 2) MOV SUM,AX ; 存和 JNO NEXT ; 无溢出, 转 NEXT LEA DX,OVER MOV AH,9 INT 21H ; 显示 Overflow! MOV AH,4CH INT 21H ; 返回 DOS ENDP 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 99

CHANGEPROC ; 转换子程序定义 MOV CL,[BX+1] ; 实际字符数送 CL MOV AL,[BX+2] ; 第一个字符送 AL 续取补 MOV CH,AL ; 暂存在 CH, 后 CMP AL, - ; 第一个字符是负号吗? JNZ NEXT1 ; 不是, 转 NEXT1 DEC CL ; 字符数减 1 INC BX NEXT1: ADD BX,2 ; 指向第一个数字字符 MOV AX,0 ; 清零 AX, 存二进制数 LP1: DEC CL JZ NEXT2 ; 若 (CL)=0, 转 NEXT2 MOV DL,[BX] ; 取字符 AND DL,0FH ; 转换成 BCD 码 ADD AL,DL ; 加到中间结果上 ADC AH,0 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 100

MOV DX,10 MUL DX ;*10 INC BX ; 指向下一个字符 JMP SHORT LP1 NEXT2: MOV DL,[BX] ; 取个位数 AND DL,0FH ; 个位 ASCII 未组合 BCD ADD AX,DX ; 加个位数,(AX)=001AH CMP CH, - ; 是 -? JNZ NEXT3 ; 该数非负, 转 NEXT3 NEG AX ; 若为负, 求补 NEXT3: MOV [DI],AX ; 存二进制结果 RET CHANGE ENDP ; CODE ENDS END START 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 101

设键入第 1 个数为 26, 第 2 个数为 33, 则在内存各变量分配如下 : STR1 STR2 NUM SUM OVER 0A 02 32( 2 ) 36( 6 ) 0D 0A 02 33( 3 ) 33( 3 ) 0D 1A 00 21 00 3B 00 O 10 个 10 个?? STR1 若键入 1234 2015 年 4 月 13 日星期一 7 时 45 分 26 秒 102 0A 04 31 32 33 34 0D 1 2 3 4

本例题重点掌握 : * 如何从键盘输入一个字符串 *ASCII 未组合 BCD 二进制 * 有符号数的运算, 对负数和溢出如何处理 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 103

3 二进制数 BCD 方法 1 计算二进制数中所包含的 1000 的个数 100 的个数 10 的个数和 1 的个数 方法 2 二进制数 ( 商 ) 除以 10 取余, 将余数按先后出现次序从右向左排列 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 104

采用方法 1 的程序流程图 Y 二进制数 AX 令 (DL)=0 (AX)-1000 <0? (DL)+1 N (AX)+1000 (AX) DL 存至缓冲区 令 (DL)=0 求 100 的个数, 结构同上 Y A (AX)-10 <0? N (DL)+1 (AX)+10 (AX) 存 DL 存 AL 返回 DOS A 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 105

汇编程序如下 : DATA SEGMENT BNUM DB 270FH DNUM DB 4 DUP(?) ; 存放 BCD 码的缓冲区 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA BINBCD PROC FAR BEGIN: MOV AX,DATA MOV DS,AX MOV AX,BNUM ; 取二进制数 LEA BX,DNUM ;BCD 码缓冲区首地址送 BX 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 106

; 计算百位的个数 MOV DL,0 ; 千位的个数计数器 AGAIN1: SUB AX,1000 ;(AX)-1000 JC NEXT1 ; 若 0, 则退出循环 INC DL ;(DL)+1 JMP AGAIN1 NEXT1: ADD AX,1000 ;(AX) (AX)+1000 MOV [BX],DL ; 存千位的个数 ; 计算百位的个数 MOV DL,0 ; 百位的个数计数器 AGAIN2: SUB AX,100 ;(AX)-100 JC NEXT2 INC DL JMP AGAIN2 NEXT2: ADD AX,100 MOV [BX+1],DL ; 存百位的个数 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 107

MOV DL,0 ; 十位的个数计数器 AGAIN3: SUB AX,10 ;(AX)-10 JC NEXT3 INC DL JMP AGAIN3 NEXT3: ADD AX,10 MOV [BX+2],DL ; 存十位的个数 MOV [BX+3],AL ; 存个位的个数 MOV AH,4CH INT 21H BINBCD ENDP ; CODE ENDS END BEGIN 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 108

4 二进制位串转换为 ASCII 码一个二进制位串若要送显示或打印, 需把串中每一位 (0 或 1) 化为 ASCII 码 思路 : 先将目标串全部预置为 30H, 再把每个二进制位逐位左移至 CF, 然后判 CF=0? 若是, 取下一位 ; 若不是, 将 31H 送此单元 流程图如下页 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 109

初始化 用 0 填满串 取要转换的数 左移 1 位 N CF=1? 存入 1 调整指针 转换完? N 结束 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 110

汇编程序如下 : DATA SEGMENT NUM DW 6F78H STRING DB 16 DUP(?) DATA ENDS ; CODE SEGMENT ASSUME CS:CODE, DS:DATA BINCA PROC FAR BEGIN: MOV AX,DATA MOV DS,AX MOV ES,AX CLD LEA DI,STRING MOV CX,16 ; 串的长度 MOV AL,30H REP STOSB ; 串中全部填充为 0 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 111

MOV CX,16 LEA DI,STRING MOV AL, 1 MOV BX,NUM ;(BX)=6F78H AGAIN: RCL BX,1 ; 含进位位循环左移 JNC NEXT ; 若为 0, 转 MOV [DI],AL ; 若为 1, 对应位送入 1 NEXT: INC DI LOOP AGAIN MOV AH,4CH ; 全部转换完毕, 返回 INT 21H ;DOS BINCA ENDP CODE ENDS END BEGIN 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 112

4.3.5 过程调用 汇编语言程序中把某些能完成特定功能而又经常要用到的程序段, 编写成独立的模块, 将它称为过程或子程序 需要执行这段程序时就进行过程调用, 执行完毕, 再返回到原来调用它的主程序去 采用过程调用结构编程, 使程序结构清晰, 语句简练不用重复编写某个程序段, 也便于修改 子程序本身又可调用其它子程序, 称为子程序嵌套 2015 年 4 月 13 日星期一 7 时 45 分 27 秒 113

4.3.5 过程调用 1. 子程序使用 掌握以下几点 : 子程序模块化 ; 子程序属性,NEAR FAR; 调用子程序用 CALL 指令, 返回调用程序用 RET 指令 ; 子程序说明的撰写, 包括 : 功能描述, 使用的寄存器 存储单元, 入口 出口参数, 调用的其他子程序名称 ; 子程序允许嵌套调用 ( 层数不限, 决定于堆栈空间 ); 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 114

4.3.5 过程调用 掌握以下几点 ( 续 ): 进入子程序后, 首先要保护主程序的运行状态 ( 标志位 ) 和使用的寄存器内容 ( 称为保护现场 ), 退出子程序前要恢复现场 调用前, 要先确定子程序中使用哪些寄存器, 并定义入口参数和出口参数 参数传递可利用寄存器 存储单元或堆栈 ( 要用 BP 寻址 ) 等几种方式 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 115

例 1 二进制数 (0-F) 转换成 ASCII( 0 - F ) 的子程 序 BIN2ASC PROC ; 要转换的二进制数在 AL 的低四位 ; 转换结果 ASCII 仍在 AL 中 CMP AL, 9 JA A2F; 高于 9, 则为 A-F ADD AL, 30H;0-9 时调整 0-9 为 ASCII 码 30-39H JMP DONE A2F: ADD AL, 37H; 否则调整 A-F 的 ASCII 为 41-46H DONE: RET BIN2ASC ENDP 调用方法 :( 在主程序中 ) MOV AL, 0CH; 采用寄存器 AL 进行参数传递行 CALL BIN2ASC (AL 中有 0CH 的 ASCII 码 43H, C ) 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 116

例 2 字符串处理程序设计 对字符串进行操作时, 往往需要确定它的长度 通常字符串结束标志以 CR(0DH) 或 $(24H) 作标志 所以可以用扫描 CR 或 $ 的方法计算出串长 在计算串长时, 应注意串长一般应小于 255 个字节 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 117

简化的主流程图 开始 求串长 求串长子程序流程 求串长 初始化指针 / 计数器串长加 1 串长 <256? Y 显示串长高位 显示串长低位 结束 N 警告 : 太长 当前字符是 $? N 搜索 CR 字符同时指针增量 找到? 存串长 返回 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 118 Y Y N

程序如下 : DATA SEGMENT STRING DB This is a string,0dh, $ LENGTH1 DW?; 串长度存放在这里 CR DB 0DH MESSAGE DB The string is too long!,0dh,0ah, $ DATA ENDS CODE MAIN BEGIN: SEGMENT ASSUME CS:CODE,DS:DATA PROC FAR MOV AX,DATA MOV ES,AX MOV DS,AX 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 119

CALL STRLEN ; 调用子程序计算串长 MOV DX,LENGTH1 ; 结果在 DX 寄存器中 CMP DX,100H JB NEXT1 ; 若 (DX)<100H, 转 LEA DX,MESSAGE ; 若 (DX) 100H, MOV AH,9 INT 21H ; 显示信息 JMP NEXT2 NEXT1: MOV DH,DL ; 串长暂存在 DH 中 MOV CL,4 SHR DL,CL ; 取串长高 4 位 CMP DL,9 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 120

JBE LP ; 9, 转 ADD DL,7 ;>9, 加 7 LP: ADD DL,30H ; 高 4 位转换为 ASCII 码 MOV AH,6 INT 21H ; 显示这个 ASCII 码 MOV DL,DH ; 取暂存串长 AND DL,0FH ; 取串长低 4 位 CMP DL,9 JBE LP1 ; 9, 转 ADD DL,7 ;>9, 加 7 LP1: ADD DL,30H ; 低 4 位转换为 ASCII 码 MOV AH,6 INT 21H ; 显示该 ASCII 码 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 121

MOV DL, H MOV AH,6 INT 21H ; 显示 H NEXT2: MOV AH,4CH INT 21H ; 返回 DOS MAIN ENDP ;------- 主程序结束 -------- ; 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 122

;----- 计算串长的子程序 ----- STRLEN PROC LEA DI,STRING MOV CX,0FFFFH ;(CX)=-1 MOV AL,CR ;(AL)=0DH MOV AH, $ ;(AH)=24H CLD ;DF=0 AGAIN: INC CX ; 串长加 1, 初始值 (CX)=0 CMP CX,100H JAE DONE ; 串长 >255, 则结束 CMP [DI],AH ; 本字符是 $? JE DONE ; 是, 则结束 SCASB ; 本字符是 CR? JNE AGAIN ; 未找到, 返回继续 DONE: MOV LENGTH1,CX; 找到,LENGTH1 串长 RET ; 返回主程序 STRLEN ENDP 2015 年 4 月 13 日星期一 7 时 45 分 28 秒 123

CODE ENDS END BEGIN 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 124

2. 子程序嵌套与递归调用 子程序格式和调用 子程序名 PROC 类型指令序列 RET 子程序名 ENDP 子程序调用与子程序返回由 CALL 和 RET 指令实现 递归调用子程序调用子程序自身 主程序 子程序 SUB1 子程序 SUB2 子程序 SUB CALL SUB1 CALL SUB2 CALL SUB3 中断点 1 中断点 2 中断点 3 RET RET RET 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 125

3. 子程序的参数传递 编写子程序时, 很重要的一个工作是如何把参数传给子程序, 这个过程叫参数传送 传送方法有 : (1) 把参数放在 CPU 内部寄存器中 (2) 把参数放在变量中 (3) 把参数放在地址表中 (4) 利用堆栈传送参数 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 126

举例介绍第 4 种方法 : 主程序中将参数或参数地址保存在堆栈中, 在子程序中将参数从堆栈取出来 例 : 将一用十六进制表示的字符 ASCII 码, 然后送到屏幕上显示 汇编程序如下 : 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 127

; DATA SEGMENT NUM DW 25AFH ; 要显示的数 STRING DB 4 DUP(?),13,10, $ DATA ENDS STACK SEGMENT DB 100 DUP(?) TOP EQU $ STACK ENDS CODE SEGMENT 堆栈 ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK BEGIN: MOV AX,DATA (SP) MOV DS,AX MOV ES,AX MOV AX,STACK MOV SS,AX MOV SP,TOP LEA BX,STRING ; 取变量偏址 PUSH BX ; 将偏址压栈 PUSH NUM ; 将变量压栈 AF 25 02 00 (TOP) 0060H 0062H 0064H 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 128

CALL BINHEX;(SP)=005EH CS:01131 LEA DX,STRING ;(DX)=0002H MOV AH,9 INT 21H MOV AH,4CH INT 21H ;*********************** BINHEX PROC PUSH BP ;(SP)=005CH2 MOV BP,SP ;(BP)=005CH PUSH AX ;(SP)=005AH PUSH DI ;(SP)=0058H PUSH CX ;(SP)=0056H PUSH DX ;(SP)=0054H (SP) 返回 (IP) 地址 1 主程序中入栈参数 原 (BP)2 13 01 AF 25 02 00 (TOP) 005CH 005EH 0060H 0062H 0064H 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 129

PUSHF ;(SP)=0052H MOV AX,SS:[BP+4] ;(AX)=25AFH MOV DI, SS:[BP+6] ;(DI)=0002H ADD DI, LENGTH STRING-4 ;(DI)=0005H MOV DX,AX ;(DX)=25AFH MOV CX,4 STD ; 从后往前存 AGAIN: AND AX,0FH ; 第一次 (AX)=000FH CALL HEXD ; 转换为 ASCII 码 STOSB PUSH CX MOV CL,4 SHR DX,CL ; 逻辑右移 4 位 MOV AX,DX ; 第 1 次 (AX)=025AH POP CX LOOP AGAIN ;(CX)-1=0? 不等, 转 (BP) +4 +6 xx xx 13 01 AF 25 02 00 (TOP) 005CH 005EH 0060H 0062H 0064H 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 130

POPF POP DX POP CX POP DI POP AX POP BP RET 4; 将返回地址后 4 字节弹出 BINHEX ENDP ;******************** (SP) HEXD PROC CMP AL,0AH JL LP ADD AL,7 LP: ADD AL,30H RET HEXD ENDP CODE ENDS END BEGIN xx xx 13 01 AF 02 25 00 (TOP) 005CH 005EH 返回的 IP 0060H 0062H 0064H 2015 年 4 月 13 日星期一 7 时 45 分 29 秒 131

从本例可知, 通过堆栈传递的两个参数分别为 : 变量 NUM 的内容 25AFH 和变量 STRING 的偏移地址 0002H 这两个参数在调用子程序之前压入堆栈, 当 CALL 指令返回时, 其 (SP)=0060H, 不是初值 0064H 故采用带参数返回指令 RET 4 本例重点掌握 : * 进一步了解堆栈的使用 * 学会 RET n 的应用 * 子程序嵌套 2015 年 4 月 13 日星期一 7 时 45 分 30 秒 132

课堂作业 统计学生成绩设有 N 个学生成绩分别为 : 试编制程序分别统计 <60 分 60 69 分 70 79 分 80 89 分 90 99 分以及 100 分的学生人数, 并分别存放于 S1 S2 S3 S4 S5 和 S6 单元中 [ 提示 ] 算法较简单, 成绩分等级部分采用分支结构, 统计所有学生部分采用循环结构完成 2015 年 4 月 13 日星期一 7 时 45 分 30 秒 133

课堂作业 流程图 AA N 开始 初始化 取一个成绩 <60? Y N <70? Y N =100? N A5 S5+1 Y S6+1 NEXT 修改地址指针 循环结束? Y 结束 计数单元循环次数首地址 S2+1 S1+1 2015 年 4 月 13 日星期一 7 时 45 分 30 秒 134 A2 A1

DATA SEGMENT grade DW xx,xx,,xx S1 DW? S2 DW? S3 DW? S4 DW? S5 DW? S6 DW? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:PUSH DS XOR AX,AX PUSH AX MOV AX,DATA MOV DS,AX MOV S1,0 2015 年 4 月 13 日星期一 7 时 45 分 30 秒 135

MOV S6,0 LEA BX,grade MOV CX,N AA:MOV AX,[BX] CMP AX,60 JL A1 CMP AX,100 JNE A5 INC S6 JMP SHORT NEXT A5: INC S5 JMP SHORT NEXT A4: A3: A2: A1: NEXT: ADD BX,2 LOOP AA CODE ENDS END START 2015 年 4 月 13 日星期一 7 时 45 分 30 秒 136

本章结束 2015 年 4 月 13 日星期一 7 时 45 分 30 秒 137