jne next inc si
cmp [si], 'G'
je yes ;是?DEBUG',转 next: inc si ;不是,地址增1 loop again ;循环
no: mov dx, offset disp2 ;没找到,显示disp2 jmp dsp
yes: mov dx, offset disp1 ;找到,显示disp1 dsp: mov ah, 09h int 21h .exit 0 end
〔习题4.21〕编程把一个16位无符号二进制数转换成为用8421BCD码表示的5位十进制数。转换算法可以是:用二进制数除以10000,商为“万位”,再用余数除以1000,得到“千位”;依次用余数除以100、10和1,得到“百位”、“十位”和“个位”。 〔解答〕
.model small .stack 256 .data
var dw 3546 dbcd db 5 dup(?) .code .startup
mov ax, var mov bx, 10000 mov cl, 10 xor si, si xor dx, dx
again: div bx mov dbcd[si], al inc si xchg ax, bx div cl xchg ax, bx cmp si,5 jnz again .exit 0 end
〔习题4.22〕过程定义的一般格式是怎样的?子程序入口为什么常有PUSH指令、出口为什么有POP指令?下面的程序段有什么不妥吗?若有,请改正: crazy PROC
push ax xor ax,ax xor dx,dx again: add ax,[bx] adc dx,0 inc bx inc bx loop again ret
ENDP crazy 〔解答〕
crazy PROC ;crazy PROC push ax ;
xor ax,ax ; xor ax,ax xor dx,dx ; xor dx,dx
again: add ax,[bx] ;again: add ax,[bx] adc dx,0 ; adc dx,0 inc bx ; inc bx inc bx ; inc bx
loop again ; loop again ret ; ret
ENDP crazy ; crazy ENDP
〔习题4.23〕子程序的参数传递有哪些方法,请简单比较。 〔解答〕
寄存器、共享变量(公共存储单元)、堆栈
用寄存器传递参数是把参数存于约定的寄存器中,这种方法简单易行,经常采用; 用变量传递参数是主程序与被调用过程直接用同一个变量名访问传递的参数,就是利用变量传递参数。如果调用程序与被调用程序在同一个源程序文件中,只要设置好数据段寄存器DS,则子程序与主程序访问变量的形式相同,也就是它们共享数据段的变量,调用程序与被调用程序不在同一个源文件中,必须利用public/extern进行声明,才能用变量传递参数,利用变量传递参数,过程的通用性比较差,然而,在多个程序段间,尤其在不同程序的模块间,利用全局变量共享数据也是一种常见的参数传递方法; 用堆栈传递参数是主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数;子程序将出口压入堆栈,主程序弹出堆栈取得它们。
〔习题4.24〕采用堆栈传递参数的一般方法是什么,为什么应该特别注意堆栈平衡问题。 〔解答〕
采用堆栈传递参数的一般方法是主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数子程序将出口参数压入堆栈,主程序弹出堆栈取得它们。因为堆栈采用“先进后出”原则存取,而且返回地址和保护的寄存器等也要存于堆栈,所以要特别注意堆栈平衡问题。
〔习题4.25〕什么是子程序的嵌套、递归和重入? 〔解答〕
子程序中又调用子程序就形成子程序嵌套。
子程序中直接或间接调用该子程序本身就形成子程序递归。 子程序的重入是指子程序被中断后又被中断服务程序所调用,能够重入的子程序称为可重入子程序。
〔习题4.26〕将例题4.7的大写转换为小写字母写成过程,利用AL作为入口、出口参数完成。 〔解答〕 .model small .stack 256 .data
stdng db 'HeLLO eveRyboDy ! ' , 0 .code .startup
mov bx, offset atring again: mov al, [bx]
call chan ;调用过程 mov [bx] , al next: inc bx jmp again done: .exit 0
chan proc ;大写转换为小写字母的过程 or al, al jz done cmp al,'A' jb next cmp al, 'Z' ja next or al, 20h ret
chan endp end
〔习题4.27〕请按如下子程序说明编写过程:
;子程序功能:把用ASCII码表示的两位十进制数转换为对应二进制数 ;入口参数:DH=十位数的ASCII码,DL=个位数的ASCII码 ;出口参数:AL=对应的二进制数 〔解答〕 astob proc
and dh, 0fh ;十位数的ASCII码转为二进制数 mov al, dh
mul 10 ;al= 10*dh
and dl, 0fh ;个位数的ASCII码转为二进制数 add al, dl ;al= 10*dh + dl ret astob endp
〔习题4.28〕写一个子程序,根据入口参数AL=0/1/2,分别实现对大写字母转换成小写、小写转换成大写或大小写字母互换。欲转换的字符串在string中,用0表示结束。 〔解答〕 Change proc
Push bx ;保护bx xor bx, bx ;位移量清零
cmp al,0 ;根据入口参数AL=0/1/2,分别处理 jz chan_0 dec al jz chan_1 dec al jz chan_2 jmp done
chan_0: mov al,string[bx] ;实现对大写字母转换成小写 cmp al,0 jz done
cmp al,?A? ;是大写字母 jb next0
cmp al,?Z? ;是大写字母 ja next0
add al, 20h ;转换 mov string[bx], al
next0: inc bx ;位移量加1,指向下一字母 jmp chan_0
chan_1: mov al,string[bx] ;实现对小写字母转换成大写 cmp al,0 jz done
cmp al,?a? ;是大写字母 jb next1
cmp al,?z? ;是大写字母 ja next1
sub al, 20h ;转换 mov string[bx], al
next0: inc bx ;位移量加1,指向下一字母 jmp chan_1
chan_2: mov al,string[bx] ;实现对大写字母转换成小写 cmp al,0 jz done
cmp al,?A? ;是大写字母
jb next2
cmp al,?Z? ;是大写字母 ja next20
add al, 20h ;转换 jmp next2
next20: cmp al,?a? ;是大写字母 jb next2
cmp al,?z? ;是大写字母 ja next2
sub al, 20h ;转换 mov string[bx], al
next2: inc bx ;位移量加1,指向下一字母 jmp chan_2
done: pop bx ;恢复bx ret change endp
〔习题4.29〕编制一个子程序把一个16位二进制数用十六进制形式在屏幕上显示出来,分别运用如下3种参数传递方法,并用一个主程序验证它。 (1)采用AX寄存器传递这个16位二进制数
(2)采用wordTEMP变量传递这个16位二进制数 (3)采用堆栈方法传递这个16位二进制数 〔解答〕
(1)采用AX寄存器传递这个16位二进制数 .model small .stack .data
wdata dw 34abh .code .startup
mov ax,wdata call dispa .exit 0 ;
dispa proc push cx push dx mov cl,4 mov dl,ah shr dl,cl call dldisp mov dl,ah and dl,0fh call dldisp