下面的程序段有错吗【精品文档-doc】
习题 6 6.1 下面的程序段有错吗? 若有,请指出错误。
CRAY PROC
PUSH AX
ADD AX,BX
RET
ENDP CRAY
【解】:CRAY PROC
PUSH AX
ADDAX,BX
RET
CRAY ENDP
6.2 写一段子程序SKIPLINES,完成输出空行的功能。空行的行数在AX寄存器中。
【解】:SKIPLINES proc near
push ax
push cx
push dx
mov cx,ax
@@1:
mov ah,2
mov dl,0dh
int 21h
mov dl,0ah
int 21h
loop @@1
pop dx
pop cx
pop ax
ret
SKIPLINES endp 6.3 设有10个学生的成绩分别是76,69,84,90,73,88,99,63,100和80分。试编制一个子程序
统计60,69分,70,79分,80,89分,90,99分和100分的人数并分别存放到S6、S7、S8、S9和S10单
元中。
【解】:data
score db 76, , 84, 90, 73, 88, 99, 63, 100, 80
s6 db 0
s7 db 0
s8 db 0
s9 db 0
s10 db 0
.code
_main:
mov ax, @data
mov ds, ax
lea si, score
mov cx, 10
cld
_next_score:
lodsb
cmp al, 60
jb _loop
cmp al,
ja _70_79
lea bx, s6
jmp _add_
_70_79:
cmp al, 79
ja _80_89
lea bx, s7
jmp _add_
_80_89:
cmp al, 89
ja _90_99
lea bx, s8
jmp _add_
_90_99:
cmp al, 100
je _100
lea bx, s9
jmp _add_
_100:
lea bx, s10
_add_:
inc byte ptr [bx]
_loop:
loop _next_score
mov ax, 4C00H
int 21H
end _main
6.4 编写一个有主程序和子程序结构的程序模块。子程序的参数是一个N字节数组的首地址TABLE,数
N和字符CHAR。要求在N字节数组中查找字符CHAR,并
该字符的出现次数。主程序则要求从键盘接收一
串字符以建立字节数组TABLE,并逐个显示从键盘输入的每个字符CHAR和它在TABLE数组中出现的次数。(为
简化起见,假设出现次数小于等于15,可以用十六进制形式把它显示出来。) 【解】:N Equ 254 ;这里假设N=255(可以自己改)
Code0 Segment
Assume SS:Code0,CS:Code0,DS:Code0
Main Proc Far
Start:
Mov AX,Code0
Mov SS,AX
Mov DS,AX
Jmp Begin
Char0 DB 0
intCount DB 0
Table DB N+1,?,N Dup (0)
strMessage DB 'Please input some characters...',10,13,36
Begin:
Lea DX,strMessage
Mov AH,9
Int 21H ;提示输入字符串
Lea DX,Table
Mov AH,10
Int 21H ;得到字符串
Push DX
Call SubProc
Exit0:
Mov AH,4CH
Int 21H
Main EndP
SubProc Proc Near
Pop AX
Pop BX
Push AX
Inc BX ;得到输入的实际字符串的长度的地址
Mov AX,BX ;备份地址,供判断用!
Add BL,[BX] ;得到该字符串的最后一个字符的地址
Push BX ;保存地址
Inc BX ;地址预先加一
Sub0:
Dec BX ;地址减一
Cmp BX,AX ;是否地址已经超出范围?
Jz Sub4 ;是
Cmp Byte Ptr [BX],0 ;该地址是否有字符?
Jnz Sub1 ;有
Jmp Sub0
Sub1:
Cmp Char0,0 ;判断是否已有字符要记数?
Jnz Sub2 ;有
Mov CH,Byte Ptr [BX]
Mov Char0,CH ;没有,置初始字符.
Sub3:
Mov Byte Ptr [BX],0 ;清空该字符
Inc intCount ;加一
Jmp Sub0
Sub2:
Mov CH,Byte Ptr [BX]
Cmp Char0,CH ;判断该地址的字符是否要记数的字符?
Jnz Sub0 ;不是
Jmp Sub3
Sub4:
Cmp Char0,Byte Ptr 0
Jz Ret0
Push AX ;保存ax
Mov CL,intCount
Mov CH,0
Push CX ;字符的个数
Call HexToDec ;转换
Mov AH,2
Mov DL,10
Int 21H
Mov DL,13
Int 21H
Mov DL,Char0
Int 21H ;显示该字符
Mov DL,'='
Int 21H ;显示“=”号
Call ShowNumber
Mov Char0,0
Mov intCount,0
Pop AX ;得到ax
Pop BX ;得到地址
Dec BX
Push BX
Cmp AX,BX ;是否所有的字符已经判断完了?
Jnz Sub5
Ret0:
Pop BX
Ret
Sub5:
Inc BX
Jmp Sub0
SubProc EndP
;16进制转换成10进制
HexToDec Proc Near
Pop BX
Pop AX ;要转换的16进制数.
Push BX ;保存sp
Xor BX,BX
Hex0:
Cmp AX,0AH
Jb Hex1 ;已经比10小了,不用再减了~
Sub AX,0AH
Add BX,10H
Cmp BL,0A0H
Jb Hex0
Add BX,100H
Xor BL,BL
Mov CL,BH
And CL,0FH
Cmp CL,0AH
Jb Hex0
Add BH,010H
And BH,0F0H
Jmp Hex0
Hex1:
Add BX,AX ;转换到此结束~
Pop AX
Push BX ;保存结果.
Push AX
Ret
HexToDec EndP
ShowNumber Proc Near
Pop AX
Pop BX
Push AX
Mov DL,BH
And DL,0F0H
Mov CL,4
Shr DL,CL
Or DL,30H
Mov AH,2
Int 21H ;显示千位
Mov DL,BH
And DL,0FH
Or DL,30H
Int 21H ;显示百位
Mov DL,BL
Mov CL,4
Shr DL,CL
Or DL,30H
Int 21H ;显示十位
Mov DL,BL
And DL,0FH
Or DL,30H
Int 21H ;显示个位
Ret
ShowNumber EndP
Code0 EndS
End Start
6.5 编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名和8个字符的电话号码,并以一定的格
式显示出来。要求主程序TELIST用于:
(1) 显示提示符INPUT_NAME:;
(2) 调用子程序INPUT_NAME输入姓名;
(3) 显示提示符INPUT A TELEPHO NENUMBER:;
(4) 调用子程序INPHONE输入电话号码;
(5) 调用子程序PRINTLINE显示姓名及电话号码;
子程序INPUT_NAME用于:
(1) 调用键盘输入子程序GETCHAR,把输入的姓名存放在INBUF缓冲区中; (2) 把INBUF中的姓名移入输出行OUTNAME。
子程序INPHONE用于:
(1) 调用键盘输入子程序GETCHAR,把输入的8位电话号码存放在INBUF缓冲区中; (2) 把INBUF中的号码移入输出行OUTPHONE。
子程序PRINTLINE:显示姓名及电话号码,格式为:
NAME TEL.
XXX XXX
【解】: dseg segment
INBUF db 32
x db ?
y db 32 dup (?)
outname db 20 dup(?)
db 8 dup (?) outphone
list1 db 'INPUT NAME:',0dh,0ah,'$'
list2 db'INPUT A TELEPHONE NUMBER:',0dh,0ah,'$'
list3 db 'NAME',22 dup (?),'TEL.',0dh,0ah,24h
zyf db 0dh,0ah,24h
dseg ends
cseg segment
assume cs:cseg,ds:dseg
start: mov ax,dseg
mov ds,ax
mov dx,offset list1
mov ah,9h
int 21h
call input_name
call zyf1
mov dx,offset list2
mov ah,09h
int 21h
call inphone
call zyf1
mov dx,offset list3
mov ah,9h
int 21h
call printline ;
call zyf1 ;可以省掉
mov dl,al ;没意义
mov ah,1h ;任意键退出,建议换8号子功能
int 21h
mov ah,4ch;程序正常退出,你忘了~
int 21h ;
zyf1 proc near
lea dx,zyf
mov ah,09h
int 21h
ret
zyf1 endp
input_name proc near
mov inbuf,19 ;限制姓名长度不超过20个字节
call getchar
mov cl,x
mov ch,0
mov si,0
z1:mov al,[y+si]
mov [outname+si],al
inc si
loop z1
mov [outname+si],24h ;如果姓名长度超过20个字节,
ret ;就存到电话号码单元里了
input_name endp
inphone proc near
call getchar
mov cl,x
mov ch,0
mov si,0
z2:mov al,[y+si]
mov [outphone+si],al
inc si
loop z2
ret
inphone endp
printline proc near
mov dx,offset outname
mov ah,9h
int 21h
mov ah,3h ;读取光标位置,主要是行号
mov bh,0 ;
int 10h ;
mov ah,2h
mov dl,1ah;置光标位置,列号
int 10h
mov si,0
mov cl,x
mov ch,0
z3:mov dl,[outphone+si]
inc si
mov ah,2h
int 21h
loop z3
ret
printline endp
getchar proc near
lea dx,INBUF
mov ah,0ah
int 21h
ret
getchar endp
cseg ends
end start
6.5 编写子程序嵌套结构的程序,把整数分别用二进制和八进制形式显示出来。主程序BANDO:把整数
字变量VAL1存入堆栈,并调用子程序PAIRS。子程序PAIRS:从堆栈中取出VAL1;调用二进制显示程序OUTBIN
显示出与其等效的二进制数;输出8个空格;调用八进制显示程序OUTOCT显示出与其等效的八进制数;调用
输出回车及换行符的子程序。
【解】:dseg segment
val dw ?
dseg ends
main segment
bando proc far
assume cs:main,ds:dseg
start:
mov ax,0
mov ax,dseg
mov ds,ax
mov bx,0
newchar: ;输入字符串
mov ah,1
int 21h
cmp al,0dh
jz oper
sub al,30h
jl exit
cmp al,9d
jg exit
cbw
xchg ax,bx
mov cx,10d
mul cx
xchg ax,bx
add bx,ax
jmp newchar
oper:
mov ax,bx
mov val,ax
call outbin
mov bx,val
mov cx,8
call space
mov bx,val
call outoct
call crlf
exit:
mov ah,4ch
int 21h
bando endp
outbin proc near ;二进制输出
mov cx,16
onebit:
rol ax,1
mov dx,ax
and dl,1
or dl,30h
push ax ;输出时破坏了寄存器ax,保存寄存器
mov ah,2
int 21h
pop ax ;输出时破坏了寄存器ax,恢复寄存器
loop onebit
ret
outbin endp
space proc near ;原来proc far
mov dl,' '
mov ah,2
int 21h
loop space
ret
space endp
outoct proc near ;进制输出
mov ax,bx
mov cx,5 ;16/3=5...1,不是4。mov cx,4是错的。
thefirstbit:
rol ax,1
mov dx,ax
and dl,1
or dl,30h
push ax ;输出时破坏了寄存器ax,保存寄存器。在这里你最好用bx作为操作数, 这样就不用来回地push pop 寄存器了。
mov ah,2
int 21h
pop ax ;输出时破坏了寄存器ax,恢复寄存器
threebit:
push cx
mov cl,3
rol ax,cl
mov dx,ax
and dl,7
or dl,30h
push ax ;输出时破坏了寄存器ax,保存寄存器
mov ah,2
int 21h
pop ax ;输出时破坏了寄存器ax,恢复寄存器
pop cx
loop threebit
ret
outoct endp
crlf proc near ;回车换行
mov ah,2
mov dl,0dh
int 21h
mov ah,2
mov dl,0ah
int 21h
ret
crlf endp
main ends
end start