![]() | 第3章 中断调用与子程序 | -41- | |||||||||||||||||||
"MicroSoft"还是很重视这个对手的,因此在DOS中特意保留了CP/M的特征,以便于和CP/M-86兼容且易于将那些为CP/M编写的应用程序移植到DOS中。由此便有了这个"CD 20",也就有了前面的"RET之谜"。 讲到此我们对CALL/RET可以说已经有较完整的印象了。不过以上对这两条指令的讨论还是很粗浅的,这里面还有更多的滋味我们还没有尝到,还需要更细致地加以咀嚼。 |
|||||||||||||||||||||
3.4 细致的咀嚼 | |||||||||||||||||||||
上一节给出了CALL指令的一种用法,这是很不全面的。这一节我们将"品尝"几个新程序,同时要"吃"出CALL指令更多的营养。请看下面的这个程序: | |||||||||||||||||||||
PROG4-B | |||||||||||||||||||||
-u100 12a[Enter] | |||||||||||||||||||||
0A3E:0100 B401 0A3E:0102 CD21 0A3E:0104 9A1F01220A 0A3E:0109 3C1B 0A3E:010B 75F3 0A3E:010D CD20 0A3E:010F 50 0A3E:0110 88C6 0A3E:0112 B780 0A3E:0114 B90800 0A3E:0117 88F3 0A3E:0119 B230 0A3E:011B 20FB 0A3E:011D 7402 0A3E:011F B231 0A3E:0121 B402 0A3E:0123 CD21 0A3E:0125 D0EF 0A3E:0127 E2EE 0A3E:0129 58 0A3E:012A CB |
MOV INT CALL CMP JNZ INT PUSH MOV MOV MOV MOV MOV AND JZ MOV MOV INT SHR LOOP POP RETF |
AH,01 21 0A3D:011F AL,1B 0100 20 AX DH,AL BH,80 CX,0008 BL,DH DL,30 BL,BH 0121 DL,31 AH,02 21 BH,1 0117 AX |
;选择DOS API的01功能 ;调用21H中断等待键盘输入 ;调用0A3D:011F处的子程序 ;输入的字符是"ESC"吗? ;不是"ESC"则转至0100H ;是"ESC"则结束程序 ;子程序开始,保存AX寄存器副本 ;输入字符的ASCII码置入DH寄存器 ;BH寄存器置入"掩膜"10000000B ;处理8个数位 ;BL寄存器置入输入字符的ASCII码 ;DL寄存器置入字符0的ASCII码30H ;将ASCII码与"掩模"相与 ;若结果为0,转至0121显示字符0 ;将字符1的ASCII码置入DL寄存器 ;选择DOS API的02H功能 ;显示DL寄存器中的字符 ;"掩模"向右移动一位 ;循环至0117处理Bit6位 ;恢复AX寄存器的原值 ;返回主程序 |
||||||||||||||||||
我们以"U"的形式给出这个程序,此程序没有存盘的必要。不过请大家务必注意不要原封不动地打入CALL指令后给出的"段:偏移"逻辑地址,因为在不同的机器上需要输入不同的段地址。段地址计算很简单,只需将CS中的实际段地址减1即可。输入程序后我们用"P"命令跟踪: | |||||||||||||||||||||
Copyright © 2004-2015 Reanimator | www.cookmoon.org |