资源描述
第4章 自测练习
一、选择题(四选一)
1.设计子程序应该采用的一对伪指令是__C_________。
A segment/ends B start/end start
C proc/endp D macro/endm
2.主程序将它的参数带给子程序,这个参数被称为 A 。
A 入口参数 B 出口参数
C 寄存器参数 D 存储器参数
3.对应主程序CALL指令调用子程序,子程序结束通常采用__D_______ 指令返回主程序。
A jmp B iret C hlt D ret
4.下面程序段条件转移语句发生跳转的条件是AL=___D_____ 。
cmp al,0fbh
jnl next
A 80h B 8fh C 0f0h D 0ffh
5.如下程序段中的“dec cx”指令执行了_C________ 次。
mov cx,4
jcxz next
again: dec cx
jnz again
next: ...
A 0 B 1 C 4 D 5
二、填空题
1.程序的基本结构有 顺序 、 分支 、 循环 和子程序四种。
2.子程序可以通过__寄存器_、存储单元、(地址表)、_堆栈_等传递参数。
3.循环结构的程序通常由 初始部分 、 循环体 和 循环控制 三部分组成。
4.如果主程序调用与它处在同一个代码段的子程序,这是 段内 调用。
5.下面程序段完成将存储单元abcd1中一个压缩型BCD码拆成两个非压缩型BCD码,高位BCD码存放在abcd3单元,低位BCD码存放在abcd2单元,再分别转换为对应的ASCⅡ码。请将程序补充完整:
mov al,abcdl
mov cl,4
shr al,cl
Or al,30h
mov abcd3,al
mov al,abcdl
and al, 0fh
orl al,30h
mov abcd2,al
6.在下述程序段的每一空框内填入一个语句,以实现如下功能:字节变量string中存放着一个字符串,以0DH为结束标志,求串长度并送字变量count中。
lea si,string
mov al,0dh
xor cx,cx
goon: cmp al,[si]
jz next
inc cx
_inc si_________
jmp goon
next: mov cont,cx
7.下述程序段运行后,AL=__88h_______、CL=__80h_ ___。
mov al,38h
mov bl,49h
call sub0
inc al
dec cl
…
sub0 proc
add al,bl
mov cl,al
daa
ret
sub0 endp
daa:加法的十进制调整指令
(AL)←把AL的和调整到压缩的BCD格式
这条指令执行前必须执行ADD或ADC指令,加法指令必须把两个压缩的BCD码相加,并把结果存放在AL寄存器中。
本指令的调整方法:若AF标志(辅助进位位)为1,或AL寄存器的低4位是16进制的A~F,则AL寄存器内容加06H,且将AF位置1。
若CF标志为1,或AL寄存器的高4位是16进制的A~F,则AL寄存器内容加60H,且将CF位置1。
DAA指令对OF标志无定义,但影响所有其他条件标志。
8.阅读如下子程序,说明它的功能:
sumary proc
xor ax,ax
xor dx,dx ;执行后,DX= 0 。
again: add ax,[bx]
adc dx,0 ;执行的操作是DX= DX+0+CF 。
inc bx
inc bx
loop again ;发生转移的条件是: cx ≠ 0 。
ret
sumary endp
子程序的入口参数:DS:BX=_16数组首地址、CX=_数据个数。
子程序的出口参数:AX=_求和结果低16位、DX=_求和结果高16位。
子程序功能为:_将CX个16位无符号数求和。
三、问答题
1. 什么是多重循环?
循环体中存在循环结构就形成多重循环。
2.于程序中为什么需要现场保护和恢复?如何实现?
主程序和子程序可能都要使用某个现场数据,例如,寄存器内容。如果子程序不进行保护,就会改变原来的内容,返回主程序后将使主程序产生错误的执行结果。所以,通常子程序开始保护现场数据,返回之前恢复原来的数据。
现场保护和恢复通常借用堆栈区实现,也可以采用特定区的方法。也就是把现成数据暂存入堆栈区域或特定存储区实现保护。实现恢复则是从堆栈或存储区取出被保护的数据。
3.试述过程定义的一般格式。
过程定义采用proc和endp一对伪指令实现,有一个用户定义的过程名(subname),可以选择是近(near)调用还是远(far)调用。这对伪指令中间是过程体,有任意合法的汇编语言语句组成,如下所示:
subname proc[near/far] ; 过程定义
....... ; 过程体
subname endp ; 过程结束
4.什么是子程序嵌套和子程序递归?
子程序中又调用子程序就形成子程序嵌套。
子程序中直接或间接调用该子程序本身就形成子程序递归。
5.说明子程序参数传递的三种主要方法。
寄存器、共享变量(公共存储单元)、堆栈
四、程序阅读题
1.dal数据区中有50个字节数据,下面程序段将每个数据的低四位变反,高四位不变,并依次存人da2数据区中。请将程序补充完整。
mov cx,50
lea si,dal
lea di,da2
K1: mov al,[si]
xor al,0fh
mov[di],al
inc si
inc di
dec cx
_____jnz k1_____________
2.下面是一个用地址表方法实现多分支的程序段。它根据xyz单元中的数据,找到地址表中的对应地址实现转移,请将程序补充完整:
xyztbl dw addr0
dw addrl
dw addr2
dw addr3
…
xyz db 2
…
lea si,xyztbl
mov ax,xyz
_add ax,ax (或shl ax,1)
add si,ax
_mov bx,[si]_
jmp bx
3.下述程序段运行后,nums开始的10个字节存储单元内容依次是什么?
nums db 0,1,2,3,4,5,6,7,8,9
…
lea si,nums
lea di,nums+l
mov cx,5
again: mov al,[si]
xchg al,[di]
mov [si],al
add si,2
add di,2
loop again
nums开始的字节存储单元内容依次是1、0、3、2、5、4、7、6、9、8。本程序依次将两个数据相互交换了一下位置。
4.下段程序的功能是什么?程序执行后BL=_7____、DL=__9__、AX=___0__
将AX逐位左移,计算其中“1”和“0”的个数。
mov ax,4bd5h
mov bl,0
mov dl,bl
mov cx,16
k1: shl ax,1
jc k2
inc bl
jmp k3
k2: inc dl
k3: loop kl
5.如下源程序的功能是,从键盘读入一字符串(长度小于40),再将该串反转后,输出显示。请在空格中添入正确的语句。
maxno equ 41
sseg segment stack
dw 100 dup(?)
sseg ends
dseg segment
mesg1 db 'Input a string:$'
mesg2 db 'Its reverse is:$'
buf db maxno,?,maxno dup(?)
dseg ends
cseg segment
assume cs:cseg,ds:dseg,ss:sseg
start: _mov ax,dseg_ ;设置数据段ds地址
mov ds,ax
mov dx,offset mesg1
mov ah,9
int 21h
mov dx,offset buf
mov ah,0ah ;利用DOS功能0AH从键盘输入一串字符
int 21h
xor ax,ax
_mov al, buf+1___ ;取实际读人字符个数
1ea di,buf+2 ;第一个字符有效地址送DI
mov si,di
add si,ax
mov byte ptr [si],'$'
;字符串结尾填入“$”,以便用DOS功能调用9号实现显示
dec si
cont: cmp di,si
_jae done ;当di≥si时结束___
;如果字符串长度是奇数,则会出现si和di相等的情况
;如果字符串长度是偶数,则会出现di大于si的情况
mov al,[si]
xchg al,[di]
mov [si],al ;前后两个字符相互交换,实现反转
dec si
inc di ;调整DI
jmp cont
done: lea dx,buf+2 ;反转后,字符串显示
mov ah,9 ;9号功能调用需要“$”结尾字符串
int 21h
mov ax,4c00h
int 21h
cseg ends
end start
五、程序设计题
1.从键盘接受一个小写字母,然后找出它的前导字符和后续字符,并按顺序输出这3个字符.
mov ah,1 ;输入一个小写字母
int 21h
push ax ;暂时保存到堆栈
push ax ;因显示功能调用回破坏AX内容
mov dl,al
dec dl ;输出前导字符
mov ah,2
int 21h
pop ax ;取出输入的字符
mov dl,al ;输出该字符
mov ah,2
int 21h
pop ax
mov dl,al ;输出后继字符
inc dl
mov ah,2
int 21h
(本题目也可以采用一个循环程序段实现)
2.假设给字节变量char预留了26个单元的空间,试编写程序段,将字母A~Z依次存放进去。
;数据段
char db 26 dup(?)
;代码段
mov al,’a’
mov bx,offset char
mov cx, 26
again: mov [bx], al
inc al
inc bx
loop again
提示:还可以采用串存储指令实现
3.编写计算100个16位正整数之和的程序。如果和不超过16位字的范围(65535),则保存其和到wordsum,如超过则显示“overflow”。
;数据段
parray dw 23,98,75…… ;假设有100个数据
wordsum dw 0
msg db ‘overflow’,’$’
;代码段
mov cx,100
mov ax,0
mov bx,offset parray
again: add ax,[bx]
jnc next
mov dx,offset msg
mov ah,9
int 21h ;显示溢出信息
jmp done ;然后跳出循环体
next: add bx,2
loop again
mov wordsum,ax
done: …
4.编写一个完整的程序,要求如下:
①采用简化段(或完整段)定义格式;
②提示输入字符串“Input string:”;
③从键盘输入一个字符串(不超过255);
④分别统计其中的大写字母和小写字母的个数(采用于程序形式);
⑤将大、小写字母个数分别存放在ucase和lcase单元中。
stack segment stack ;定义堆栈段
db 1024 dup(0)
stack ends
data segment ;定义数据段
msg db ‘Input string:’0dh,0ah,’$’
string db 255
db ?
db 255 dup(?)
lcase db 0
ucase db 0
data ends
code segment ;定义代码段
assume cs:code,ds:data,ss:stack
start: mov ax,data ;程序开始点
mov ds,ax
mov ah,9 ;提示输入字符串
mov dx,offset msg
int 21h
mov ah,0ah ;从键盘接受字符串
mov dx,offset string
int 21h
mov bx,offset string+2 ;设置入口参数
mov cl,[bx-1] ;DS:BX指向字符串首地址
xor ch,ch ;CX等于字符串长度
call slength ;调用子程序,统计大小写字母的个数
mov lcase,al ;处理出口参数:AL=小写字母个数
mov ucase,ah ;AH=大写字母个数
mov ax,4c00h
int 21h ;程序结束,返回DOS
;子程序:采用寄存器传递入口参数和出口参数
slength proc
push dx
xor ax,ax
slen1: mov dl,[bx] ;取出一个字符
cmp dl,’A’ ;判断是否为大写字母
jb slen3 ;小于“A”,不是字母
cmp dl,’Z’
ja slen2 ;不是大写字母,可能是小写字母
inc ah ;是大写字母,则大写字母个数加1
jmp slen3
slen2: cmp dl,’a’ ;判断是否为小写字母
jb slen3
cmp dl,’z’
ja slen3
inc al ;是小写字母,则小写字母个数加1
slen3: inc bx
loop slen1
pop dx
ret
slength endp
code ends
end start
8
展开阅读全文