第六章子程序结构-1
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例6.3:十进制到十六进制数转换(通过寄存器传送参数) :十进制到十六进制数转换(通过寄存器传送参数)
decihex segment 16 ;10 assume cs:decihex main proc far push ds sub ax, ax push ax repeat: call decihex 2 ;10 call crlf ;回车换行 call binihex 16 ;2 call crlf jmp repeat ret main endp ...... decihex ends end main
segment proc far ... ret
code main
segment proc far ... call ... ret subr1
subt
subt
endp ... call subt ...
main subr1
endp proc near ... ret
segx segy
ends segment ... call far ptr subt ...
1 a f 31 61 66
5、判断若小于10,则转到构成多位十六进制数 判断若小于10, 10 6、再减去27H,判断是否是‘a’~’f’ 再减去27H,判断是否是‘ ~ 27H 7、若非‘a’~’f’,则退出 若非‘ ~ ,
((0×16)+1) × 16+0a) × 16+0f
8、构成多位十六进制数,所有前面输入的数应扩大十 构成多位十六进制数, ↑ 六倍 9、加上刚输入的数,形成完整的多位十六进制数 加上刚输入的数, 10、继续键入,直到输入非0 10、继续键入,直到输入非0~9或非‘a’~’f’的数 或非‘ ~ 的数
【例】从键盘接收十进制数并存入 BX
…… mov newchar: mov int sub jl cmp jg cbw xchg mov mul xchg add jmp …… bx, 0 ah, 1 21h al, 30h exit al, 9 exit
1 2 5 31 32 35
;键盘输入
<0退出 ; <0退出 ; >9退出 >9退出
1 a f 31 61 66
;键盘输入
<0退出 ; <0退出
; ‘a’~‘f’ <‘a’退出 ; <‘a’退出 >’f’退出 ; >’f’退出 ((0×16)+1) × 16+0a) × 16+0f
例6.3:十进制到十六进制数转换(通过寄存器传送参数) :十进制到十六进制数转换(通过寄存器传送参数) 开始 调用DECIBIN 调用 调用CRLF 调用 显示回车换行 调用BINIHEX 调用 调用CRLF 调用 结束 用十六进制形式 显示BX中的数 显示 中的数 从键盘取得十进制 保存在BX中 数,保存在 中
【例】从键盘接收十六进制数并存入 BX
…… mov newchar: mov int sub jl cmp jl sub cmp jl cmp jge add_to: mov shl mov add jmp exit: …… bx, 0 ah, 1 21h al, 30h exit al, 10 add_to al, 27h al, 0ah exit al, 10h exit cl, 4 bx, cl ah, 0 bx, ax newchar
subr1 code
endp ends
segy
ends
6.1.2 子程序的调用和返回
子程序调用: 子程序调用:隐含使用堆栈保存返回地址 call near ptr subp (1) 保存返回地址 (2) 转子程序 (SP) (IP) call far ptr subp (1) 保存返回地址 (SP) (IP) (2) 转子程序 (CS) 子程序返回: 子程序返回:ret
一、通过寄存器传递参数
【例】从键盘接收十进制数并存入 BX
算法: 算法: 1、初始化BX=0 初始化BX=0 2、键盘输入并回显 3、转成二进制数(用ASCII-30H来完成) 转成二进制数( ASCII-30H来完成) 来完成 4、判断若非0~9的数,则退出 判断若非0 的数,
1 2 5 31 32 35
binihex
exit: decibin
ret endpБайду номын сангаас
proc mov rotate: mov rol mov and add cmp jl add printit: mov mov int dec jnz ret binihex endp
near ch,4 cl,4 bx,cl al,bl al,0fh al,30h al,3ah printit al,7h dl,al ah,2 21h ch rotate
DEC BX JNZ LP2;延时 ;延时1s POP CX POP BX POPF RET
从上面的子程序我们可以看出: 从上面的子程序我们可以看出:子程序中因 为用到了BX, 和标志寄存器 和标志寄存器, 为用到了 ,CX和标志寄存器,所以程序 一开始就用了3条 指令, 一开始就用了 条PUSH指令,把这些寄存器 指令 内容压进堆栈,以保护CPU的现场;而在返 的现场; 内容压进堆栈,以保护 的现场 回前,它又用了3条 指令(遵循 回前,它又用了 条POP指令 遵循“先入后 指令 遵循“ 出”的原则 把栈中内容弹回到寄存器中去。 的原则)把栈中内容弹回到寄存器中去 把栈中内容弹回到寄存器中去。 当然, 当然,这些保护现场和恢复现场的工作在主 程序不怕丢失这些内容时,可以不用, 程序不怕丢失这些内容时,可以不用,或者 放在主程序中解决,但一般来说, 放在主程序中解决,但一般来说,放在子程 序中更妥当,也更通用些。 序中更妥当,也更通用些。
【例】延时程序,在实际应用中一般作为子程序调用, 延时程序,在实际应用中一般作为子程序调用, 现在我们把延时1s的程序设计成子程序 的程序设计成子程序。 现在我们把延时 的程序设计成子程序。 程序内容如下:(省略段的定义) :(省略段的定义 程序内容如下:(省略段的定义) DELAY1S: PUSHF ;现场保护 : 现场保护 PUSH BX PUSH CX MOV BX,3E8H;1000D , ; LP2: MOV CX,176H : , LP1: PUSHF : POPF LOOP LP1;延时 ;延时1ms
ax, cx, cx ax, bx,
bx 10 bx ax
( ( 0×10)+1 )×10+2 )×10+5 × × ×
newchar
exit:
【例】从键盘接收十六进制数并存入 BX
算法: 算法: 1、初始化BX=0 初始化BX=0 2、键盘输入并回显 3、转成二进制数(用ASCII-30H来完成) 转成二进制数( ASCII-30H来完成) 来完成 4、判断若小于0,则退出 判断若小于0
decibin
proc mov newchar: mov int sub jl cmp jg cbw xchg mov mul xchg add jmp
near bx,0 ah, 1 21h al, 30h exit ;<0返主 返主 al, 9d exit ;>9返主 返主 ax, bx cx, 10d cx ax, bx bx, ax newchar
( ( 0×10)+1 )×10+2 )×10+5 × × ×
5、扩展成16位(因为采集的是多位数) 扩展成16位 因为采集的是多位数) 16
↑
6、采集本位数时,所有前面输入的数应扩大十倍 采集本位数时, 7、加上刚输入的数,形成完整的多位十进制数 加上刚输入的数, 8、继续键入,直到输入非0~9的数为止 继续键入,直到输入非0
crlf
crlf
proc mov mov int mov mov int ret endp
near dl, 0dh ah, 2 21h dl, 0ah ah, 2 21h
章练习( 第6章练习(第十次) 章练习 第十次) Page 240 6.1~6.3
6.1.1 过程定义伪操作 过程名 PROC 过程名 ENDP 属性: (1) NEAR属性:调用程序和过程在同一个 ) 属性 段内调用) 代码段中 (段内调用) 属性: (2) FAR属性:调用程序和过程不在同一个 ) 属性 段间调用) 代码段中 (段间调用) NEAR (FAR) )
…
segx
例如,一个任意数的平方;把一组数进行排序; 例如,一个任意数的平方;把一组数进行排序;多倍 精度的二—十进制数相加 十进制数相加; 精度的二 十进制数相加;十进制数与二进制数的 转换等等,都可以编成子程序来调用。 转换等等,都可以编成子程序来调用。这种工作不 仅对学习子程序来说是必要的,而且, 仅对学习子程序来说是必要的,而且,对于熟练编 也是必不可少的。 程,积少成多也是必不可少的。 另外,值得提出的是: 另外,值得提出的是:子程序方式也可以利用到编写 大型复杂的程序中去。也就是说,我们可以把一个 大型复杂的程序中去。也就是说,
6.1.4 子程序的参数传送
1. 通过寄存器传递参数 2. 通过存储器传递参数 (过程和调用程序在同一源程序文件中 则过程 过程和调用程序在同一源程序文件中,则过程 过程和调用程序在同一源程序文件中 可直接访问模块中的变量) 可直接访问模块中的变量 3. 通过地址表传送参数地址 4. 通过堆栈传送参数或参数地址 5. 多个模块之间的参数传送问题
第六章 子程序结构
6.1 子程序的设计方法 6.2 子程序的嵌套 6.3 子程序举例 6.4 DOS系统功能调用 系统功能调用
6.1 子程序的设计方法
6.1.1 过程定义伪操作 6.1.2 子程序的调用和返回 6.1.3 保护与恢复寄存器 6.1.4 子程序的参数传送 6.1.5 增强功能的过程定义伪操作
复杂的程序分割成很多独立的,关联较少的模块, 复杂的程序分割成很多独立的,关联较少的模块, 分别编写成子程序,然后,用一个主程序(主要由调 然后, 用子程序指令构成)把它们串联起来。这样的程序不
但结构清晰,而且对调试也带来极大的方便。 但结构清晰,而且对调试也带来极大的方便。这一 点,在具体实践中会有更深刻的体会。
6.1.3 保护与恢复寄存器
SUBT PROC PUSH PUSH PUSH PUSH …… …… POP POP POP POP SUBT RET ENDP NEAR AX BX CX DX DX CX;若CX和DX位置互换 意义如何 位置互换,意义如何 若 和 位置互换 意义如何? BX;原则上除了实现过程通信的 ; AX;量以外都要进行现场保护 ;
在编写实际子程序时要注意下列问题: 在编写实际子程序时要注意下列问题: (1) 入口信息 。 (2) 出口信息。 (3) 现场的保护和恢复。先仔细观察子程序中到底用 了哪些寄存器, 了哪些寄存器,以便主程序调用它时注意保护和恢 复现场。 复现场。 (4) 最后一条一定是RET指令。 在这一节里,我们只举了例1一个简单的子程序 一个简单的子程序, 在这一节里,我们只举了例 一个简单的子程序,但 在实际应用中, 在实际应用中,我们可以把各种功能的程序编成子 程序。 程序。