第6章 子程序结构 在程序设计中,我们会发现一些多次无规律重复的程序段或语句序列。解决此类问题一个行之有效的方法就是将它们设计成可供反复调用的独立的子程序结构,以便在需要时调用。在汇编语言中,子程序又称过程。 调用子程序的程序称为主调程序或主程序。 2019/7/20 ch6.

Slides:



Advertisements
Similar presentations
输入输出程序设计 输入输出的基本概念 无条件方式输入输出 查询方式输入输出 中断方式输入输出.
Advertisements

汇编语言程序设计 吴 向 军 中山大学计算机科学系
微型计算机技术 教 学 指 导(七) 太原广播电视大学 郭建勇.
第10章 DOS功能调用与BIOS中断调用.
第7章 8086/8088汇编语言程序设计 7.1 引言 7.2 顺序程序设计 7.3 分支结构程序设计 7.4 循环结构程序设计
第四章 汇编语言 程序设计 任课教师:王晓甜
大连理工大学软件学院 软件工程系 赖晓晨 计算机组成与结构 大连理工大学软件学院 软件工程系 赖晓晨
第一章 计算机基础知识 第一节 计算机概述 一、计算机的基本组成和工作原理 二、有关术语 三、计算机发展简史 四、微型计算机概述
汇编语言与接口技术 教师:范新民.
输入/输出及接口 输入/输出的传送方式 中断技术 80x86/Pentium中断系统 8259A可编程中断控制器 中断程序设计
本周实验安排 实验内容:(P231)人名排序的例子。
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年10月30日.
第3章 80x86汇编语言程序设计(下).
第3章 80x86汇编语言程序设计(中) 时间不够的情况下只讲16位汇编.
4.1 汇编语言 4.2 顺序结构程序 4.3 分支程序设计 4.4 循环程序设计 4.5 子程序设计
第3章 80x86汇编语言程序设计(上) 16位汇编版本 时间不够的情况下只讲16位汇编.
9.1 可编程并行输入/输出接口芯片8255A 9.2 可编程计数器/定时器 可编程串行输入/输出接口芯片8251A
3.3.5 程序控制指令 控制转移指令分为: 转移指令 循环控制指令 调用和返回指令 中断指令.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月26日.
第5章 循环与分支程序设计  循环程序设计  分支程序设计.
汇编语言程序设计 Assembly Language Programming
第三章 寻址方式与指令系统 3.1 寻址方式 一条指令通常由两大部分构成: 操作码 操作数
第6章 DMA传输 6.1 DMA传输原理 6.2 DMA控制器8237A A的编程使用 欢迎辞.
第7章 并行接口 7.1 简单并行接口 7.2 可编程并行接口8255A 7.3 键盘接口 7.4 LED显示器接口.
第2章 MCS-51单片机指令系统与汇编语言程序设计
微机原理与接口技术 第2章 8086系统结构 朱华贵 2015年09月17日.
第九章 计数器和定时器电路 第一节 概述 第二节 Intel 8253的控制字 第三节 Intel 8253的工作方式 第九章 计数器和定时器电路 第一节 概述 第二节 Intel 8253的控制字 第三节 Intel 8253的工作方式 第四节 Intel 8253在IBM PC机上的应用.
Assembly Language Programming
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年12月10日.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月05日.
输入输出与中断 主要内容 CPU与外设之间数据传送方式 中断技术 8086中断系统和中断处理.
第八章 输入输出程序设计 总线 CPU MEM I/O接口 I/O设备.
第3章 IA-32指令系统 3.1 基本数据类型 3.2 IA-32的指令格式 3.3 IA-32指令的操作数寻址方式
第8章 寻址方式与指令系统.
第4章 汇编语言程序设计 4.1 程序设计语言概述 4.2 汇编语言的程序结构与语句格式 4.3 汇编语言的伪指令
微机原理及应用 主讲:谢维成 西华大学 电气信息学院 1.
基本的”防”黑客技术 Basic” ” Hacker Technique
微机原理及应用 主讲:郑海春.
第一章 8086程序设计 第二章 MCS-51程序设计 第三章 微机基本系统的设计 第四章 存贮器与接口 第五章 并行接口
汇编语言程序设计课程设计 第二次实验 DEBUG基本命令与算术运算指令
计算机原理及系统结构 第十八讲 主讲教师:赵宏伟                 学时:64.
微型计算机原理及应用.
第3章 微型计算机输入输出接口 3.1 输入/输出接口 3.2 输入输出数据传输的控制方式 3.3 开关量输入输出接口 欢迎辞.
第六章 子程序结构 §6.1 子程序的设计方法 §6.2 嵌套与递归子程序 §6.3 子程序举例 §6.4 DOS系统功能调用.
1.3 微型计算机的结构和工作原理.
第 13 章 中断系统.
條件處理.
第九章 高级宏汇编语言 9.1 结构 结构就是将逻辑上有一定关系的一组数据,以某种方式组合在一起所形成的数据形式。
第5章 循环与分支程序设计 学习目标: 了解并掌握循环程序的构造方法,尤其是对循环控制条件的设置以及可能出现的边界情况的考虑。掌握起泡排序算法这种多重循环程序设计中的常用方法。交换标志位的设置在此算法中更能提高效率。学会在数组排序算法中采用折半查找法来提高查找效率。学会使用跳跃表法实现CASE结构。
4.1 汇编语言程序格式 4.2 MASM中的表达式 4.3 伪指令语句 4.4 DOS系统功能调用和BIOS中断调用
3.4.5 控制转移指令(Control transfer instructions) (一)、控制转移指令概述
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月19日.
第五章:输入输出基本技术 主讲教师:范新民.
第4章 汇编语言程序格式  汇编程序功能  伪操作  汇编语言程序格式  汇编语言程序的上机过程.
第10章 可编程外围接口芯片8255A及其应用 10.1 概述 A的工作原理 A的应用举例.
习题3 1、 分别说明下列指令的原操作数和目的操作数各采用什么寻址方式。 设定如下: ①立即寻址 ② ① ②寄存器寻址
可编程定时计数器.
第九章 BIOS和DOS中断 在存储器系统中,从地址0FE000H开始的8K ROM(只读存储器)中装有BIOS(Basic Iuput /output System)例行程序。驻留在ROM中的BIOS给PC系列的不同微处理器提供了兼容的系统加电自检,引导装入,主要I/O设备的处理程序以及接口控制等功能模块来处理所有的系统中断。使用BIOS功能调用,给程序员编程带来很大方便,程序员不必了解硬件操作的具体细节,直接用指令设置参数,然后中断调用BIOS中的子功能,所以利用BIOS功能编写的程序简洁,可读性好,
第2章 80x86计算机组织  计算机系统  存储器  中央处理机  外部设备.
《微型计算机原理与接口技术》 第4版 王良 宁德师范学院 吴宁 乔亚男 编著 清华大学出版社 出版
第5章 循环与分支程序设计  循环程序设计  分支程序设计.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年12月17日.
第八章 中断系统.
微机原理与接口技术 西安邮电大学计算机学院 宁晓菊.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月06日.
微机原理与接口技术 第5章 汇编语言程序设计 西安邮电大学计算机学院 王 钰.
大数据搜索挖掘实验室 第五章 子程序设计 张华平 副教授 博士 Website: 大数据搜索挖掘实验室
第4章 MCS-51汇编语言程序设计 教学基本要求: (1)、了解MCS-51汇编语言程序设计的特点;
第4章 汇编语言程序格式  汇编程序功能  伪操作  汇编语言程序格式  汇编语言程序的上机过程
第三章 8086的指令系统 8086指令特点 8086的寻址方式 8086的指令格式及数据类型 8086的指令集.
Presentation transcript:

第6章 子程序结构 在程序设计中,我们会发现一些多次无规律重复的程序段或语句序列。解决此类问题一个行之有效的方法就是将它们设计成可供反复调用的独立的子程序结构,以便在需要时调用。在汇编语言中,子程序又称过程。 调用子程序的程序称为主调程序或主程序。 2019/7/20 ch6

子程序的结构 子程序的基本结构包括以下几个部分: (1)子程序定义 (2)保护现场和恢复现场 (3)子程序体 (4)子程序返回 2019/7/20 ch6

6.1.1 子程序的定义 6.1 子程序的设计方法 子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下: 6.1 子程序的设计方法 6.1.1 子程序的定义 子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下: 过程名 PROC [NEAR/FAR] ┆ 过程名 ENDP 其中PROC表示过程定义开始,ENDP表示过程定义结束。过程名是过程入口地址的符号表示。 一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性(NEAR 和 FAR)。 2019/7/20 ch6

6.1.2 子程序的调用和返回 如果调用程序和过程在同一代码段中,则使用NEAR属性; MAIN PROC FAR 6.1.2 子程序的调用和返回 如果调用程序和过程在同一代码段中,则使用NEAR属性; MAIN PROC FAR … CALL SUBR1 RET MAIN ENDP ; SUBR1 PROC NEAR SUBR1 ENDP MAIN PROC FAR … CALL SUBR1 RET SUBR1 PROC NEAR SUBR1 ENDP MAIN ENDP 2019/7/20 ch6

SEGX SEGMENT SEGX ENDS SEGY SEGMENT SEGY ENDS 如果调用程序和过程不在同一代码段中,则使用FAR属性; SEGX SEGMENT … SUBT PROC FAR RET SUBT ENDP CALL SUBT SEGX ENDS ; SEGY SEGMENT SEGY ENDS 2019/7/20 ch6

6.1.3 保护现场和恢复现场 PROG PROC PROC ENDP 例如:若子程序PROG中改变了寄存器AX,BX,CX,DX的值,则 可采用如下方法保护和恢复现场。 PROG PROC PUSH AX PUSH BX PUSH CX ;保护现场 PUSH DX ┆ POP DX POP CX POP BX ;恢复现场 POP AX RET ;返回断点处 PROC ENDP 2019/7/20 ch6

6.1.4 主程序与子程序参数传递方式 1 通过寄存器传送参数 这是最常用的一种方式,使用方便,但参数很多时不能使用这种方法。 6.1.4 主程序与子程序参数传递方式 1 通过寄存器传送参数 这是最常用的一种方式,使用方便,但参数很多时不能使用这种方法。 例:十进制到十六进制转换的程序。程序要求从键盘取得一个十进制数,然后把该数以十六进制的形式在屏幕上显示出来。 开始 从键盘取得十进制 数,保存到BX中 调用DECIBIN 调用CRLF 显示回车和换行 调用BINIHEX 用十六进制形式 显示BX中的数 调用CRLF 结束 2019/7/20 ch6

Decihex segment Decibin proc near mov bx, 0 Newchar: mov ah, 1 int 21h sub al, 30h jl exit cmp al, 9 jg exit cbw xchg ax, bx mov cx, 10 mul cx xchg ax, bx ;每次乘的 add bx, ax ;结果在BX中 jmp newchar Exit : ret Decibin endp Decihex segment assume cs:Decihex Main proc far Repeat: push ds xor ax, ax push ax call decibin call crlf call binihex ret Main endp 2019/7/20 ch6

Decihex ends Binihex proc near mov ch, 4 Rotate: mov cl, 4 rol bx, cl mov dl, bl and dl, 0fh add dl, 30h cmp dl, 3ah jl print add dl, 7h Print: mov ah, 2 int 21h dec ch jnz rotate ret Binihex endp Crlf proc near mov ah, 2 mov dl, odh int 21h mov dl, oah ret Crlf endp Decihex ends end repeat 2019/7/20 ch6

如果过程和调用过程在同一源文件(同一模块)中,则过程可直接访问模块中的变量。 例 6.4 主程序MAIN和过程PROADD在同一源文件中,要求用过程PROADD累加数组的所有元素,并把和(不考虑溢出的可能性)送到指定的存储单元中去 2019/7/20 ch6

CODE SEGMENT CODE ENDS PROADD PROC NEAR PUSH AX DATA SEGMENT PUSH CX PUSH SI PUSH DI LEA SI ,ARY MOV CX ,COUNT XOR AX , AX NEXT: ADD AX , [SI] ADD SI , 2 LOOP NEXT MOV SUM , AX POP DI POP SI POP CX POP AX RET PROADD ENDP CODE ENDS END START DATA SEGMENT ARY DW 100 DUP (?) COUNT DW 100 SUM DW ? DATA ENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE , DS:DATA START: PUSH DS SUB AX ,AX PUSH AX MOV AX , DATA … CALL NEAR PTR PROADD RET MAIN ENDP 2019/7/20 ch6

3 通过地址表传递参数 PROADD PROC NEAR PUSH AX PUSH CX PUSH SI CODE SEGMENT 3 通过地址表传递参数 PROADD PROC NEAR PUSH AX PUSH CX PUSH SI MOV SI , MOV CX , MOV DI , XOR AX , AX NEXT: ADD AX , [SI] ADD SI , 2 LOOP NEXT MOV , AX POP SI POP CX POP AX RET PROADD ENDP CODE ENDS END START CODE SEGMENT ARY DW 100 DUP(?) COUNT DW 100 SUM DW ? NUM DW 100 DUP (?) N DW 100 TOTAL DW ? ; MOV TABLE , OFFSET ARY MOV TABLE+2, OFFSET COUNT MOV TABLE+4 , OFFSET SUN MOV BX , OFFSET TABLE CALL PROADD ;计算SUM [BX] [BX+2] [BX+4] [DI] 2019/7/20 ch6

4 通过堆栈传递地址或参数 例:把内存中字变量num的值,转换为4个用ASCⅡ码表示的16进制数码,串的起始地址为string 。 sp 4 通过堆栈传递地址或参数 Data segment Num dw 25afh String db 4 dup(?), ‘$’, 0dh, 0ah Data ends Stack segment para stack ‘stack’ db 100 dup(?) Stack ends Code segment assume cs:code, ds:data, ss:stack Main proc far Begin: push ds xor ax, ax push ax mov ax,data mov ds, ax lea bx, string push bx push num call binhex lea dx, string mov ah, 9 int 21h ret Main endp 2000:0000 2000:0002· 例:把内存中字变量num的值,转换为4个用ASCⅡ码表示的16进制数码,串的起始地址为string 。 3000:0000 3000:0001 3000:0003 3000:0004 3000:0007 3000:0009 3000:000d 3000:000e 3000:0012 3000:0015 3000:0019 sp 15 00 Lea dx,string 地址(IP) af 25 02 00 Num string地址 2019/7/20 ch6

Binhex proc near push bp mov bp,sp push ax push di push bx push cx pushf mov ax, [bp+4] ; ax=25afh mov di, [bp+6] ; di=0002 mov ch, 4 mov cl, 4 roat: rol ax ,cl mov bl, al and bl, 0fh add bl, 30h cmp bl, 39h jle next add bl, 7h sp flag cx bx di ax bp Bp-6 Bp-4 Bp-2 (Sp→)bp 0015 bp+2 bp+4 bp+6 Lea dx,string地址(IP) 25af 0002 Num string地址 2019/7/20 ch6

Next: mov [di], bl inc di dec ch jnz rota popf pop cx pop bx pop di pop ax pop bp ret 4 Binhex endp Code ends end begin sp flag cx bx di ax bp sp 0015 Lea dx,string地址(IP) 25af 0002 Num string地址 2019/7/20 ch6

例3:求10个数的累加值. --------远调用 例3:求10个数的累加值. --------远调用 Data segment Ary db 10 dup(?) Count db 10 Sum db ? Data ends Stack segment para stack ‘stack’ db 100 dup(?) Stack ends Code1 segment assume cs:code1, ds:data, ss;stack Main proc far Start: push ds xor ax, ax push ax mov ax, data mov ds, ax 2019/7/20 ch6

Push bx Mov bx, offset count Mov bx, offset sum Call far ptr proadd Mov bx, offset ary Push bx Mov bx, offset count Mov bx, offset sum Call far ptr proadd mov al, sum mov dl, al mov ah, 2 int 21h ret Main endp Code1 ends sp IP CS MOV AL, SUM 地址 Sum地址 Count地址 Ary地址 2019/7/20 ch6

Code2 segment assume cs:code2 Proadd proc far push bp mov bp, sp push ax push cx push si push di mov si, [bp+0ah] mov di, [bp+08h] mov cl, [di] mov di, [bp+06h] xor al, al Again: add al, [si] inc si dec cl jnz again mov [di], al pop di pop si pop cx di si cx ax bp sp (Sp→)bp IP CS MOV AL, SUM 地址 [bp+06h] Sum地址 Count地址 Ary地址 [bp+08h] [bp+0ah] pop ax pop bp ret 6 Proadd endp Code2 ends end start 2019/7/20 ch6

5 多个模块之间的参数传送问题 (1) PUBLIC伪指令 格式:PUBLIC 符号 [,符号] 5 多个模块之间的参数传送问题 (1) PUBLIC伪指令 格式:PUBLIC 符号 [,符号] 功能:说明其后的符号是全局符号。全局符号能被其他模块引用。(局部符号) (2) EXTRN伪指令 格式:EXTRN 符号:类型 [,符号:类型] 功能:说明在本模块中需要引用的、由其他模块定义的符号,即外部符号。 2019/7/20 ch6

注意:应先有public 定义,然后才有extrn说明 source module 1 extrn a:word Data1 segment b dw ? Data1 ends code1 segment assume cs:code1,ds:data1 Main proc far start: mov ax , data1 mov ds,ax … mov ah,4ch int 21h Main endp Code1 ends End start source module 2 public a Data2 segment a dw ? Data2 ends code2 segment assume cs:code2,ds:data2 Main proc far start: mov ax , data2 mov ds,ax … mov ah,4ch int 21h Main endp Code2 ends End start 注意:应先有public 定义,然后才有extrn说明 2019/7/20 ch6

例:用模块化程序设计方法建立两个模块MOD1 ASM和MOD2 ASM的数据通讯。 NAME MOD1 EXTRN DISP:FAR PUBLIC STR1,N ,BUF DATA1 SEGMENT STR1 DB ‘HOW DO YOU DO?’ N = $-STR1 BUF DB ‘THIS IS AN EXAMPLE OF MODULES PROGRAM $′ DATA ENDS STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE1 SEGMENT ASSUME CS:CODE1,DS:DATA1,SS:STACK START: MOV AX,DATA MOV DS,AX CALL DISP MOV AH,4CH INT 21H CODE1 ENDS END START 2019/7/20 ch6

EXTRN STR1:BYTE,STR2:BYTE,N:ABS PUBCIC DISP DATA2 SEGMENT NAME MOD2 EXTRN STR1:BYTE,STR2:BYTE,N:ABS PUBCIC DISP DATA2 SEGMENT STR2 DB 81 DUP(0) DATA2 ENDS CODE2 SEGMENT ASSUME CS:CODE2,ES:DATA2 DISP PROC FAR MOV AX,DATA2 MOV ES,AX LEA BX,STR1 MOV CX,N LEA SI,STR2 NEXT: MOV AL,[BX] MOV ES:[SI],AL INC BX INC SI LOOP NEXT LEA DX,BUF MOV AH,9 INT 21H RET DISP ENDP CODE2 ENDS END 2019/7/20 ch6

6.1.5 增强功能的过程定义伪操作 Procname PROC [attributes field] [USER register list] [,parameter field] … Procname ENDP Attributes field(属性字段)包括: Distance : near 、far Language type :说明是那种高级语言的子程序 如pascal 、c 等。 Visibility : 说明程序的可见性 是private 或是public。 Prologue :是一个宏的名字,允许用宏来控制过程的入口或出口有关的代码 USER:该字段用来指定用户所需保存和恢复的寄存器表。 Parameter field: 参数字段 ,允许用户指定该过程所用的参数 。 标识符:类型[,标识符:类型] 2019/7/20 ch6

例6 .4 用增强功能过程定义伪操作实现 Data segment Ary db 10 dup(?) Count db 10 例6 .4 用增强功能过程定义伪操作实现 Data segment Ary db 10 dup(?) Count db 10 Sum db ? Data ends Stack segment para stack ‘stack’ db 100 dup(?) Stack ends Code1 segment assume cs:code1, ds:data, ss:stack Main proc far Start: push ds xor ax, ax push ax mov ax, data mov ds, ax Mov bx, offset ary Push bx Mov bx, offset count Mov bx, offset sum Call far ptr proadd mov al, sum mov dl, al mov ah, 2 int 21h ret Main endp Code1 ends 2019/7/20 ch6

( bp +4) ( bp +6) ( bp +8) ( bp +a) Code2 segment assume cs:code2 Proadd proc far push bp mov bp, sp push ax push cx push si push di mov si, [bp+0ah] mov di, [bp+08h] mov cl, [di] mov di, [bp+06h] xor al, al Again: add al, [si] inc si dec cl jnz again mov [di], al pop di pop si pop cx pop ax pop bp ret 6 Proadd endp Code2 ends end start Code2 segment assume cs:code2 Proadd proc pascal user ax cx si di , para:word,parc:word,pars:word mov si, para mov di, parc mov cl, [di] mov di, pars xor al, al Again: add al, [si] inc si dec cl jnz again mov [di], al ret Proadd endp Code2 ends end start di si cx ax 局部变量 ( bp -2) (bp) 原始bp ( bp +2) IP CS mov al, sum ( bp +4) ( bp +6) Sum地址 Count地址 Ary地址 para ( bp +8) parc ( bp +a) pars 2019/7/20 ch6

增强功能的过程定义伪操作除了以上功能外 ,还可以在过程中定义局部变量。局部变量是在过程内部使用的变量,他是在过程调用是在堆栈中建立的,在退出过程是被释放。 可以用 LOCAL 定义 LOCAL 变量:类型[,变量:类型] ( bp -4) 局部变量 ( bp -2) (bp) 原始bp ( bp +2) IP CS ( bp +4) ( bp +6) Sum地址 Count地址 Ary地址 ( bp +8) ( bp +a) 2019/7/20 ch6

6.2 子程序的嵌套 一个子程序可以作为调用程序去掉用另一个子程序,这种情况称为子程序的嵌套。嵌套深度不限。但应注意什么问题? 6.2 子程序的嵌套 一个子程序可以作为调用程序去掉用另一个子程序,这种情况称为子程序的嵌套。嵌套深度不限。但应注意什么问题? 堆栈溢出:上溢、下溢 递归子程序:如果一个子程序调用的是子程序的本身,就是递 归子程序。 2019/7/20 ch6

例5: 计算 N!=N*(N-1)*(N-2)* ……*1 --------递归子程序 Data segment Num db 3 Result dw ? Data ends Stack segment para stack ‘stack’ db 100 dup(?) Stack ends Code segment assume cs:code, ds:data, ss:stack Main proc far Begin: push ds xor ax, ax push ax mov ax, data mov ds, ax 2019/7/20 ch6

mov ah, 0 mov al, num call factor mov result, ax ret Main endp Factor proc push ax sub ax, 1 jne f_cont pop ax jmp return f_cont: call factor pop cx mul cl return: ret factor endp Code ends end begin ax =1 1 IP POP CX 地址 IP3 Pop cx 地址 ax*cx =1*2 cx =2 2 IP POP CX 地址 IP2 Pop cx 地址 ax*cx =1*2*3 cx =3 3 IP Mov result, ax 地址 IP1 Mov result, ax 地址 2019/7/20 ch6

常用的DOS系统功能调用 1.单字符输入(1号调用) 2.单字符显示(2号调用) 3.打印输出(5号调用) 4.结束调用(4CH号调用) 5.显示字符串(9号调用) 6.字符串输入(10号调用) 2019/7/20 ch6

功能:从键盘输入字符的ASCII码送入寄存器AL中,并送显示器显示。 1.单字符输入(1号调用) 格式:MOV AH,1   INT 21H 功能:从键盘输入字符的ASCII码送入寄存器AL中,并送显示器显示。 2.单字符显示(2号调用) 格式:MOV DL,待显示字符的ASCII码   MOV AH,2   INT 21H 功能:将DL寄存器中的字符送显示器显示. 2019/7/20 ch6

格式:MOV DL,待打印字符的ASCII码 MOV AH,5 INT 21H 功能:将DL寄存器中的字符送打印机打印。 3.打印输出(5号调用) 格式:MOV DL,待打印字符的ASCII码  MOV AH,5  INT 21H 功能:将DL寄存器中的字符送打印机打印。 4.结束调用(4CH号调用) 格式:MOV AH,4CH   INT 21H 功能:终止当前程序并返回调用程序。 2019/7/20 ch6

maxlen db 32 lea dx , maxlen 5.显示字符串(9号调用) 格式:LEA DX,待显示字符串首偏移地址   MOV AH,9   INT 21H 功能:将当前数据区中以‘$’结尾的字符串送显示器显示。 6.字符串输入(10号调用) 格式:LEA DX,缓冲区首偏移地址 MOV AH,10 INT 21H 功能:从键盘上输入一字符串到用户定义的输入缓冲区中,并送显示器显示。 说明:缓冲区的第一个字节保存最大字符数,这个最 大字符数由用户程序给出。如果键入的字符数 比此数大,机器发出嘟嘟声。第二个字节存放 实际输入的字节数,这个不是由用户填入的而 由功能A填入的。在这两个字节之后,才是我们 输入的字符串。 maxlen db 32 actlen db ? string db 32 dup(?) lea dx , maxlen mov ah,0ah int 21h 2019/7/20 ch6

6.3 子程序举例 例1:HEXIDEX是一个十六进制数转换成十进制数的程序。要求把从键盘输入的0 — FFFFH的十六进制正数转换为十进制数并在屏幕上显示出来。 Display equ 2h Key equ 1h Doscall equ 21h Hexidec segment Main proc far assume cs:hexidec Start: push ds sub ax,ax push ax call hexidec call crlf call binidec call crlf jmp main ret main endp Crlf proc near mov dl ,0ah mov ah,display int boscall mov dl,0dh mov ah,display int doscall ret crlf endp Hexidec ends end start 2019/7/20 ch6

Hexidec proc near mov bx ,0 Binidec proc near mov cx , 10000d Newchar: mov key_in int doscall sub al,30h jl exit cmp al, 10d jl add_to sub al ,27h cmp al,0ah jl exit cmp ah,10h jge exit Add_to: mov cl ,4 shl bx , cl mov ah ,0 add bx,ax jmp Exit: Ret Hexidec endp Binidec proc near mov cx , 10000d call dec_div mov cx , 1000d mov cx,100d mov cx,10d mov cx,1d ret Dec_div proc near mov ax, bx mov dx ,0 div cx mov bx,dx mov dl,al add dl,30h mov ah,display int doscall ret dec_div endp Binidec endp 2019/7/20 ch6

例2:一个简单的信息检索系统。在数据区里,有10个不同的信息,编号为0—9,每个信息包括30个字符。现在要编制一个程序:从键盘接收0—9之间的一个编号,然后在屏幕上显示相应编号的信息的内容。 Datarea segment thirty db 30 msg0 db ‘ 0 I like my IBM-PC--------------’ msg1 db ‘ 1 I like my IBM-PC--------------’ msg2 db ‘ 2 I like my IBM-PC--------------’ msg3 db ‘ 3 I like my IBM-PC--------------’ msg4 db ‘ 4 I like my IBM-PC--------------’ msg5 db ‘ 5 I like my IBM-PC--------------’ msg6 db ‘ 6 I like my IBM-PC--------------’ msg7 db ‘ 7 I like my IBM-PC--------------’ msg8 db ‘ 8 I like my IBM-PC--------------’ msg9 db ‘ 9 I like my IBM-PC--------------’ errmsg db ‘error!!! Invalid praameter’ Datarea ends 2019/7/20 ch6

assume cs:prognam ,ds:datarea,ss:stack Start: push ds xor ax,ax Stack segment db 256 dup(0) tos lable word Stack ends Prognam segment assume cs:prognam ,ds:datarea,ss:stack Start: push ds xor ax,ax push ax mov ax,stack mov ss,ax mov ax,datarea mov ds,ax mov sp,offset tos Begin:mov ah,1 int 21h sub al,’0’ jc error cmp al, ‘9’ ja error Mov bx,offset msg0 Mul thirty Add bx,ax Call display Jmp begin Error: mov bx,offset errmsg call display ret Display proc near mov cx,30 mov dl,[bx] call dispchar inc bx loop disp1 mov dl,0dh call dispchar mov dl,0ah Dispchar endp Dispchar proc naer mov ah,2 int 21h ret Dispchar endp Main endp Prognam ends End start 2019/7/20 ch6

例3:人名排序程序。先从终端键入最多30个人名,当所有人名都进入后,按字母上升的次序将人名排序,并在屏幕上显示已经排好的人名。 2019/7/20 ch6

messg2 db ‘sorted names’,13,10,’$’ namectr db 0 Data segment namepar label byte maxnlen db 21 namelen db ? namefld db 21 dup(?) crlf db 13,10,’$’ endaddr dw ? messg1 db ‘name?’,’$” messg2 db ‘sorted names’,13,10,’$’ namectr db 0 nametab db 30 dup (20 dup(‘ ’)) namesav db 20 dup (?),13,10,’$’ swapped db 0 Data ends Code segment main proc far assume cs:code,ds:data,es:data start:push ds mov ax,0 push ax mov ax,data mov ds,ax mov es,ax cld lea di,nametab a20loop:call b10read cmp namelen,0 jz a30 cmp namectr,30 je a30 call d10stor jmp a20loop a30:cmp namectr,1 jbe a40 call g10sort call k10disp a40:mov ah,4ch Int 21h Main endp 2019/7/20 ch6

b10read endp mov ah,09 inc namectr lea dx ,messg1 cld int 21h b10read proc near mov ah,09 lea dx ,messg1 int 21h mov ah,0ah lea dx,namepar int 21h mov ah,09h lea dx crlf Int 21h mov bx,0 mov bl ,namelen mov cx,21 sub cx,bx b20: mov namefld[bx],20h inc bx loop b20 ret b10read endp d10stor proc near inc namectr cld lea si , namectr mov cx,10 rep movsw ret p10stor endp g10sort proc near sub di ,40 mov endaddr,di g20: mov swapped,0 lea si,nametab g30: mov cx,20 mov di,si add di,20 add ax,di mov ax,di mov bx,si repe cmpsb jbe g40 call h10xchg g40: mov si,ax cmp swapped,0 jnz g20 ret G10sort endp 2019/7/20 ch6

mov ah,09 mov cx,10 lea dx,messg2 lea di , namesav int 21h mov si,bx k10disp proc near mov ah,09 lea dx,messg2 int 21h lea si,nametab lea di,namesav mov cx,10 rep movsw lea dx, namesav dec namectr jnz k20 ret K10disp endp end start h10xchg proc near mov cx,10 lea di , namesav mov si,bx rep movsw mov di,bx rep movsw mov cx ,10 lea si,namesav rep movsw mov swapped,1 ret h10xchg endp 2019/7/20 ch6

第六章 作业 6.1 6.2 6.3 6.7 2019/7/20 ch6