11.1 写出文件代号式磁盘存取操作的错误代码:
(1) 非法文件代号 (2) 路径未发现 (3) 写保护磁盘
答:错误代码为:
(1) 06 (2) 03 (4) 19
11.2 使用3CH功能建立一文件,而该文件已经存在,这时会发生什么情况?
答:此操作将文件长度置为0,写新文件,原文件内容被清除。

11.3 从缓冲区写信息到一个文件,如果没有关闭文件,可能会出现什么问题?
答:文件结尾的部分信息就没有被写入磁盘,从而造成写入的文件不完整。
11.4 下面的ASCIZ串有什么错误?
PATH_NAME DB ‘C:\PROGRAMS\TEST.DAT’
答:此ASCIZ串的最后少了一个全0字节,应改为:
PATH_NAME DB ‘C:\PROGRAMS\TEST.DAT’, 0
11.5 下面为保存文件代号定义的变量有什么错误?
FILE_HNDL DB ?
答:文件代号是字类型,因此应改为:
FILE_HNDL DW ?
11.6 在ASCPATH字节变量中为驱动器D的文件PATIENT.LST,请定义ASCIZ串。
答:ASCPATH DB ‘D:\PATIENT.LST’, 0
11.7 对11.6题中的文件,它的每个记录包含:
病例号(patient number): 5字符, 姓名(name): 20字符,
城市(city): 20字符, 街道(street address): 20字符,
出生年月(mmddyy): 6字符, 性别(M/Fcode): 1字符,
病房号(room number): 2字符, 床号(bed number): 2字符,
(1) 定义病人记录的各个域 (2) 定义保存文件代号的变量FHANDLE
(3) 建文件 (4) 把PATNTOUT中的记录写入
(5) 关文件 (6) 以上文件操作包括测试错误
答:(1) PATNTOUT EQU THIS BYTE
patient DB 5 DUP (?)
name DB 20 DUP (?)
city DB 20 DUP (?)
street DB 20 DUP (?)
mmddyy DB 6 DUP (?)
M_Fcode DB ?
room DB 2 DUP (?)
bed DB 2 DUP (?), 0AH, 0DH

COUNT = $-PATNTOUT ;记录长度
(2) FHANDLE DW ?
(3) MOV AH, 3CH ;建文件功能
MOV CX, 00 ;普通文件属性
LEA DX, ASCPATH
INT 21H
JC ERROR
MOV FHANDLE, AX ;保存文件代号
(4) MOV AH, 40H ;写文件功能
MOV BX, FHANDLE ;取文件代号
MOV CX, COUNT ;记录长度
LEA DX, PATNTOUT ;记录的首地址
INT 21H
JC ERROR
CMP AX, COUNT ;所有的字节都写入了吗?
JNE ERROR1
(5) MOV AH, 3EH ;关闭文件功能
MOV BX, FHANDLE ;取文件代号
INT 21H
JC ERROR
(6) 文件操作的测试错误已包括在(3)、(4)、(5)的操作中。
11.8 对11.7题的文件,用文件代号式编写一个完整的读文件程序,读出的每个记录存入PATNTIN并在屏幕
上显示。
答:程序如下:
TITLE READDISP.EXE ;利用文件代号式顺序读文件程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h

.data
endcde db 0 ;结束处理指示
fhandle dw ?
patntin db 80 DUP(‘ ’) ;DTA
ascpath db ‘d:\patient.lst’, 0
openmsg db ‘***open error***’, 0dh, 0ah
readmsg db ‘***read error***’, 0dh, 0ah
row db 0
;-------------------------------------------------------------
.code
begin proc far
mov ax, @data
mov ds, ax
mov es, ax
mov ax, 0600h
call screen ;清屏
call curs ;设置光标
call openh ;打开文件,设置DTA
cmp endcde, 0 ;打开错误吗?
jnz a0 ;错误,转结束
contin: call readh ;读磁盘记录
cmp endcde, 0 ;读错误吗?
jnz a0 ;错误,转结束
call disph ;没错,显示记录
jmp contin
a0: mov ax, 4c00h ;退出程序,返回DOS
int 21h
begin endp

;-------------------------------------------------------------
;打开文件
openh proc near
mov ah, 3dh
mov al, 0
lea dx, ascpath
int 21h
jc b1 ;打开错误吗?
mov fhandle, ax ;没有错,保存文件代号
ret
b1: mov endcde, 01 ;打开错误,指示结束处理
lea dx, openmsg
call errm ;显示出错信息
ret
openh endp
;-------------------------------------------------------------
;读磁盘记录
readh proc near
mov ah, 3fh
mov bx, fhandle
mov cx, 80
lea dx, patntin
int 21h
jc c1 ;读错误吗?
cmp ax, 0 ;文件已读完吗?
je c2 ;读完,退出
ret
c1: lea dx, openmsg ;读错误
call errm ;显示出错信息

c2: mov endcde, 01 ;读错误或文件读完,指示结束处理
ret
readh endp
;-------------------------------------------------------------
;显示记录
disph proc near
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 80
lea dx, patntin
int 21h
cmp row, 24 ;已到屏幕底部吗?
jae d1 ;已到屏幕底部,退出
inc row
ret
d1: mov ax, 0601h
call screen ;屏幕上卷一行
call curs ;设置光标
ret
disph endp
;-------------------------------------------------------------
;屏幕上卷
screen proc near ;入口参数为ax
mov bh, 1eh ;设置颜色
mov cx, 0 ;屏幕左上角
mov dx, 184fh ;屏幕右下角
int 10h
ret
screen endp

;-------------------------------------------------------------
;设置光标
curs proc near
mov ah, 2 ;设置光标
mov bh, 0
mov dh, row ;行号
mov dl, 0 ;列号
int 10h
ret
curs endp
;-------------------------------------------------------------
;显示出错信息
errm proc near
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 20
int 21h
ret
errm endp
;-------------------------------------------------------------
end begin
11.9 编写建立并写入磁盘文件的程序。允许用户从键盘键入零件号(3字符),零(配)件名称(12字符),单
价(1个字)。程序使用文件代号式建立含有这些信息的文件。注意要把单价从ASCII码转换为二进制数。下面是
输入的例子:
part# Description price part# Description price
023 Assemblers 00315
024 Linkages 00430
027 Compilers 00525
049 Compressors 00920

114 Extractors 11250
117 Haulers 00630 122 Lifters
10520
124 Processors 21335
127 Labtlers 00960
232 Bailers 05635
237 Grinders 08250
999 000
答:程序如下:
TITLE HANCREAT.EXE ;利用文件代号式建立文件程序
;-------------------------------------------------------------
.model small
.stack 100h
.data
prompt1 db 'Please input Part#: $' ;提示输入零件号
prompt2 db 'Please input Description: $' ;提示输入零件名称
prompt3 db 'Please input Price: $' ;提示输入单价
maxlen db 13 ;最大输入长度,输入字符串功能的缓冲区
actlen db ? ;实际输入长度
buffer db 13 DUP (' ') ;输入字符串缓冲区
crlf db 0dh, 0ah, '$'
pathname db 'filename.lst', 0
handle dw ?
dta db 19 DUP (' ') ;DTA
errcde db 0 ;错误处理指示
opnmsg db '***open error***', 0dh, 0ah
wrtmsg db '***write error***', 0dh, 0ah
;-------------------------------------------------------------
.code

begin proc far
mov ax, @data
mov ds, ax
mov es, ax
mov ax, 0600h
call scren ;清屏
call curs ;设置光标
call creath ;建立文件
cmp errcde, 0 ;建立错误吗?
jnz a0 ;错误,转结束
contin: call proch ;记录处理
cmp actlen, 0 ;输入的字符串长度为0,结束输入吗?
jne contin ;不结束,继续
call clseh ;结束输入,关闭文件
a0: mov ax, 4c00h ;退出程序,返回DOS
int 21h
begin endp
;-------------------------------------------------------------
;建立文件
creath proc near
mov ah, 3ch
mov cx, 0 ;普通属性
lea dx, pathname
int 21h
jc bbb ;建立文件错误吗?
mov handle, ax ;没有错,保存文件代号
ret
bbb: lea dx, opnmsg ;建立文件错误

call errm ;显示出错信息
ret
creath endp
;-------------------------------------------------------------
;接收输入
proch proc near
cld
lea di, dta ;在di中设置dta的首地址
lea dx, prompt1 ;输入零件号
mov bx, 3 ;零件号最多3个字符
call in_proc
jc exit ;没有输入,结束
lea dx, prompt2 ;输入零件名称
mov bx, 12 ;零件名称最多12个字符
call in_proc
jc exit ;没有输入,结束
lea dx, prompt3 ;输入单价
mov bx, 5 ;零件单价最多5个十进制字符(相当于一个二进制字)
call in_proc
call dec_bin ;将十进制的单价转换为二进制的单价
mov word ptr [dta+17], 0a0dh ;在DTA的最后插入回车换行符
call writh ;用文件代号法写记录
exit: ret
proch endp
;-----------------------------------------------------------------
;输入字符串子程序
in_proc proc near
mov ah, 09h ;显示提示信息
int 21h

push di
lea di, buffer ;在buffer中填入空格符
mov cl, maxlen
mov ch, 0
mov al, ' '
rep stosb
pop di
mov ah, 0ah ;输入字符串
lea dx, maxlen
int 21h
call disp_crlf
cmp actlen, 0 ;实际输入字符数=0,则没有输入,结束
je end_in
push di
lea di, buffer ;在buffer的后面填入空格符
mov al, actlen
mov ah, 0
add di, ax
mov cl, maxlen
mov ch, 0
mov al, actlen
sub cl, al
mov al, ' '
rep stosb
pop di
lea si, buffer ;将buffer缓冲区内容送入dta
mov cx, bx
rep movsb ;将输入内容送入dta
clc ;有输入字符,返回(cf)=0

jmp in_end
end_in: stc ;没有输入字符,返回(cf)=1
in_end: ret
in_proc endp
;-----------------------------------------------------------------
;将十进制的单价转换为二进制的单价子程序
dec_bin proc near
mov bx, 0
mov si, 0
mov cx, 5
transfer: mov al, buffer[si] ;从十进制的高位到低位取数
cmp al, 0dh ;是回车吗?
je dec_bin1
cmp al, ' ' ;是空格吗?
je dec_bin1
and al, 0fh ;将ascii码转换为十进制数
mov ah, 0
push cx
xchg ax, bx ;十进制数高位×10+低位 = 二进制数
mov cx, 10
mul cx
xchg ax, bx
add bx, ax ;转换的二进制数在(bx)中
pop cx
inc si
loop transfer
dec_bin1: mov word ptr [dta+15], bx ;存入单价到dta中的单价位置
ret
dec_bin endp

;-----------------------------------------------------------------
;用文件代号法写记录
writh proc near
mov ah, 40h
mov bx, handle
mov cx, 19
lea dx, dta
int 21h
jnc ddd ;写文件错误吗?
lea dx, wrtmsg
call errm ;显示出错信息
mov actlen, 0
ddd: ret
writh endp
;-----------------------------------------------------------------
;用文件代号法关闭文件
clseh proc near
mov dta, 1ah ;写文件结束符1ah
call writh
mov ah, 3eh
mov bx, handle
int 21h
ret
clseh endp
;-------------------------------------------------------------
;屏幕上卷
scren proc near ;入口参数为ax
mov bh, 1eh ;设置颜色
mov cx, 0 ;屏幕左上角

mov dx, 184fh ;屏幕右下角
int 10h
ret
scren endp
;-------------------------------------------------------------
;设置光标
curs proc near
mov ah, 2 ;设置光标
mov bh, 0
mov dh, 0 ;行号
mov dl, 0 ;列号
int 10h
ret
curs endp
;-------------------------------------------------------------
;显示出错信息
errm proc near
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 20
int 21h
mov errcde, 01 ;错误代码置1
ret
errm endp
;-------------------------------------------------------------
disp_crlf proc near ; 显示回车换行符子程序
lea dx, crlf
mov ah, 09h
int 21h

ret
disp_crlf endp ; disp_crlf子程序结束
; -----------------------------------------------------------
end begin ;汇编语言源程序结束
11.10 编写一个程序使用文件代号式读出并显示11.9题建立的文件。注意,要把二进制数表示的单价转换为
ASCII码。
答:用文件代号式读出并显示文件,程序如下:
TITLE HANDREAD.EXE ;利用文件代号式顺序读并显示文件程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h
.data
endcde db 0 ;结束处理指示
crlf db 0dh, 0ah, '$'
pathname db 'filename.lst', 0
message db ' Part# Description Price',0dh,0ah,'$'
handle dw ?
tackline db ' | $'
dta db 19 DUP (' ') ;DTA
errcde db 0 ;错误处理指示
opnmsg db '***open error***', 0dh, 0ah
readmsg db '***read error***', 0dh, 0ah
row db 0
;-------------------------------------------------------------
.code
begin proc far
mov ax, @data

mov ds, ax
mov es, ax
mov ax, 0600h
call screen ;清屏
call curs ;设置光标
lea dx, message ;显示标题
mov ah, 09h
int 21h
inc row
call openh ;打开文件,设置DTA
cmp endcde, 0 ;打开错误吗?
jnz a0 ;错误,转结束
contin: call readh ;读磁盘记录
cmp endcde, 0 ;读错误吗?
jnz a0 ;错误,转结束
call disph ;没错,显示记录
jmp contin
a0: mov ax, 4c00h ;退出程序,返回DOS
int 21h
begin endp
;-------------------------------------------------------------
;打开文件
openh proc near
mov ah, 3dh
mov al, 0
lea dx, pathname
int 21h
jc bbb ;打开错误吗?

mov handle, ax ;没有错,保存文件代号
ret
bbb: mov endcde, 01 ;打开错误,指示结束处理
lea dx, readmsg
call errm ;显示出错信息
ret
openh endp
;-------------------------------------------------------------
;读磁盘记录
readh proc near
mov ah, 3fh
mov bx, handle
mov cx, 19
lea dx, dta
int 21h
jc c1 ;读错误吗?
cmp ax, 0 ;文件已读完吗?
je c2 ;读完,退出
cmp dta, 1ah ;文件结束符吗?
Je c2
ret
c1: lea dx, opnmsg ;读错误
call errm ;显示出错信息
c2: mov endcde, 01 ;读错误或文件读完,指示结束处理
ret
readh endp
;-------------------------------------------------------------
;显示记录
disph proc near

lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 3
lea dx, dta
int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 12
lea dx, dta+3
int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov si, word ptr [dta+15]
call bin_dec ;转换为十进制数显示
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
call disp_crlf
cmp row, 24 ;已到屏幕底部吗?
jae ddd ;已到屏幕底部,退出
inc row
ret

ddd: mov ax, 0601h
call screen ;屏幕上卷一行
call curs ;设置光标
ret
disph endp
;-----------------------------------------------------------------
;将二进制的单价转换为十进制的单价并显示子程序
bin_dec proc near
push cx
mov cx, 10000d
call dec_div ;调除法并显示输出子程序
mov cx, 1000d
call dec_div
mov cx, 100d
call dec_div
mov cx, 10d
call dec_div
mov cx, 1d
call dec_div
pop cx
ret
bin_dec endp
;--------------------------------------------------------------------------
;除法并显示输出子程序
dec_div proc near
mov ax, si
mov dx, 0
div cx
mov si, dx ;余数保存在(si)中作下一次的除法

mov dl, al ;商(在00h~09h范围内)送(dl)
add dl, 30h ;转换为0~9的ascii码
mov ah, 02h ;显示输出
int 21h
ret
dec_div endp
;-----------------------------------------------------------------
;屏幕上卷
screen proc near ;入口参数为ax
mov bh, 1eh ;设置颜色
mov cx, 0 ;屏幕左上角
mov dx, 184fh ;屏幕右下角
int 10h
ret
screen endp
;-------------------------------------------------------------
;设置光标
curs proc near
mov ah, 2 ;设置光标
mov bh, 0
mov dh, row ;行号
mov dl, 0 ;列号
int 10h
ret
curs endp
;-------------------------------------------------------------
;显示出错信息
errm proc near
mov ah, 40h ;向标准输出设备(文件代号=01)写文件

mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 20
int 21h
ret
errm endp
;-------------------------------------------------------------
disp_crlf proc near ;显示回车换行符子程序
lea dx, crlf
mov ah, 09h
int 21h
ret
disp_crlf endp ; disp_crlf子程序结束
; -----------------------------------------------------------
end begin
11.11 对11.9题建立的文件按下面的要求编写程序:
(1) 把所有的记录读入内存的数据缓冲区TABLE;
(2) 显示字符串提示用户输入零(配)件号及其数量;
(3) 按零件搜索TABLE;
(4) 如果发现所要求的零件,用它的单价计算出总价(单价×数量);
(5) 显示零(配)件说明及总价值。
答:程序如下:
TITLE READ11.EXE ;利用文件代号式读并计算显示程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h
.data
endcde db 0 ;结束处理指示
pathname db 'filename.lst', 0

in_mes1 db '请输入3位数的零件号Part#:', '$'
in_mes2 db '请输入该零件的数量:', '$'
out_mes1 db '输入的不是数字!请重新输入数字:’, '$'
out_mes2 db '输入的零件号不存在!请重新输入3位数的零件号Part#:', '$'
in_buffer db 6, ?, 6 dup(20h) ;输入缓冲区
message db ' Part# Description Sum_Price', 0dh, 0ah,'$'
tackline db ' | $'
sum_price dw 0, 0
decimal db 10 DUP(0), ‘$’
crlf db 0dh, 0ah, '$'
handle dw ?
table db 19*100 DUP(' ') ;table,足够大
errcde db 0 ;错误处理指示
opnmsg db '***open error***', 0dh, 0ah
readmsg db '***read error***', 0dh, 0ah
;-------------------------------------------------------------
.code
begin proc far
mov ax, @data
mov ds, ax
mov es, ax
mov ax, 0600h
call screen ;清屏
call curs ;设置光标
call openh ;打开文件,设置TABLE
cmp endcde, 0 ;打开错误吗?
jnz a0 ;错误,转结束
call readh ;读磁盘记录

cmp endcde, 0 ;读错误吗?
jnz a0 ;错误,转结束
call in_Part ;没错,输入零件号和零件数量
a0: mov ax, 4c00h ;退出程序,返回DOS
int 21h
begin endp
;-------------------------------------------------------------
;打开文件
openh proc near
mov ah, 3dh
mov al, 0
lea dx, pathname
int 21h
jc bbb ;打开错误吗?
mov handle, ax ;没有错,保存文件代号
ret
bbb: mov endcde, 01 ;打开错误,指示结束处理
lea dx, opnmsg
call errm ;显示出错信息
ret
openh endp
;-------------------------------------------------------------
;读磁盘记录
readh proc near
mov ah, 3fh
mov bx, handle
mov cx, 19*100 ;准备读入的字节数
lea dx, table
int 21h

jc c1 ;读错误吗?
cmp ax, 0 ;文件已读完吗?
je c2 ;读完,退出
cmp table, 1ah ;文件结束符吗?
Je c2
mov bp, ax ;读成功则在AX中返回实际读入的字节数存入bp
ret
c1: lea dx, readmsg ;读错误
call errm ;显示出错信息
c2: mov endcde, 01 ;读错误或文件读完,指示结束处理
ret
readh endp
;-------------------------------------------------------------
;输入零件号和零件数量
in_Part proc near
lea dx, in_mes1 ;显示提示信息,提示输入零件号
in_Part1: call input ;输入数据
cmp in_buffer+1, 3 ;输入的零件号个数是3位吗?
lea dx, out_mes2 ;显示提示信息,提示重新输入零件号
jne in_Part1
cld
mov ax, bp ;取实际读入文件的字节数
mov cl, 19 ;每个记录的长度为19个字符
div cl ;计算实际读取的记录数在al中
mov bl, al
mov bh, 0 ;从第0个记录开始顺序查找
in_Part2: lea si, in_buffer+2 ;查找零件号对应的零件
lea di, table
mov al, 19

mul bh
add di, ax ;计算某个记录的首地址
mov word ptr decimal, di ;保存首地址
mov cx, 3
repe cmpsb
je in_Part3 ;找到对应的零件
inc bh ;找下一个记录
cmp bh, bl
jb in_Part2
jmp in_Part1 ;未找到对应的零件重新输入
in_Part3: lea dx, in_mes2 ;显示提示信息,提示输入零件数量
call input ;输入数据
call dec_bin ;将输入数据转换为二进制数,在bx中
mov di, word ptr decima ;di指向该记录的首地址
mov ax, [di+15] ;取单价
mul bx ;总价格在(dx),(ax)中
mov sum_price, ax
mov sum_price+2, dx
call disp_rec ;显示信息
ret
in_Part endp
;-------------------------------------------------------------
;输入数据
input proc near
input1: mov ah, 09h ;显示字符串
int 21h
mov ah, 0ah ;输入字符串
lea dx, in_buffer
int 21h

lea dx, out_mes1 ;显示提示信息
mov cl, in_buffer+1
cmp cl, 0 ;输入的数字个数为0吗?
jz input1
mov ch, 0
mov bx, 2
input2: mov al, in_buffer[bx] ;输入的是数字0~9吗?
cmp al, ‘0’
jb input1
cmp al, ‘9’
ja input1
inc bx
loop input2
ret
input endp
;-------------------------------------------------------------
;将十进制数转换为二进制数子程序
dec_bin proc near
mov bx, 0
mov si, 2
mov cl, in_buffer+1
mov ch, 0
transfer: mov al, in_buffer[si] ;从十进制的高位到低位取数
and al, 0fh ;将ascii码转换为十进制数
mov ah, 0
push cx
xchg ax, bx ;十进制数高位×10+低位 = 二进制数
mov cx, 10
mul cx

add bx, ax ;转换的二进制数在(bx)中
pop cx
inc si
loop transfer
ret
dec_bin endp
;-----------------------------------------------------------------
;显示记录
disp_rec proc near
call disp_crlf
lea dx, message ;显示标题
mov ah, 09h
int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 3 ;显示3位数的零件号
mov dx, word ptr decima ;dx指向该记录的首地址
int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 12 ;显示12位的零件说明
mov dx, word ptr decima ;dx指向该记录的首地址
add dx, 3

int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
call bin_dec ;总价格转换为十进制数显示
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
call disp_crlf
ret
disp_rec endp
;-----------------------------------------------------------------
;4字节二进制数转换为10进制子程序
bin_dec proc near
mov bx, 0 ;10字节的bcd码单元清0
mov cx, 10
bin_dec1: mov decimal[bx], 0
inc bx
loop bin_dec1
mov cx, 4*8 ;4字节二进制数共4*8=32位
bin_dec2: mov bx, 10-1 ;计算
(((a31*2+a30)*2+a29)...)*2+a0
shl word ptr [sum_price],1 ;4字节二进制数左移1位
rcl word ptr [sum_price +2],1
push cx
mov cx, 10
bin_dec3: mov al, decimal[bx] ;计算(...)*2+ai,ai由进位位带入
adc al, al
aaa ;非压缩bcd码加法调整

mov decimal[bx], al
dec bx
loop bin_dec3
pop cx
loop bin_dec2
call disp
ret
bin_dec endp
;--------------------------------------------------------------------------
disp proc near ;显示输出子程序
mov cx, 10
mov bx, 0
disp1: add decimal[bx], 30h ;变为ascii码
inc bx
loop disp1
mov cx, 10 ;下面5条指令是为了不显示数据左边的“0”
cld
lea di, decimal
mov al, 30h ;30h为“0”的ascii码
repe scasb
dec di
mov dx, di
mov ah, 09h
int 21h
ret
disp endp ;disp子程序结束
;---------------------------------------------------------------------------
;屏幕上卷
screen proc near ;入口参数为ax

mov bh, 1eh ;设置颜色
mov cx, 0 ;屏幕左上角
mov dx, 184fh ;屏幕右下角
int 10h
ret
screen endp
;-------------------------------------------------------------
;设置光标
curs proc near
mov ah, 2 ;设置光标
mov bh, 0
mov dh, 0 ;行号
mov dl, 0 ;列号
int 10h
ret
curs endp
;-------------------------------------------------------------
;显示出错信息
errm proc near
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 20
int 21h
ret
errm endp
;-------------------------------------------------------------
disp_crlf proc near ;显示回车换行符子程序
lea dx, crlf
mov ah, 09h

int 21h
ret
disp_crlf endp ; disp_crlf子程序结束
; -----------------------------------------------------------
end begin
11.12 用随机处理记录的方式编写程序,将用户需要的零(配)件记录读取到TABLE,并根据键入的数量,计
算出总价值,然后显示出零(配)件说明及总价值。
答:程序如下:
TITLE READ_RAN.EXE ;利用文件代号式随机读并计算显示程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h
.data
endcde db 0 ;结束处理指示
pathname db 'filename.lst', 0
in_mes1 db '请输入3位数的零件号Part#:', '$'
in_mes2 db '请输入该零件的数量:', '$'
out_mes1 db '输入的不是数字!请重新输入数字:’, '$'
out_mes2 db '输入的零件号不存在!请重新输入3位数的零件号Part#:', '$'
in_buffer db 6, ?, 6 dup(20h) ;输入缓冲区
message db ' Part# Description Sum_Price', 0dh, 0ah,'$'
tackline db ' | $'
sum_price dw 0, 0
decimal db 10 DUP(0), ‘$’
crlf db 0dh, 0ah, '$'
handle dw ?
table db 19 DUP(' ') ;table
errcde db 0 ;错误处理指示

opnmsg db '***open error***', 0dh, 0ah
readmsg db '***read error***', 0dh, 0ah
movmsg db '***move error***', 0dh, 0ah
;-------------------------------------------------------------
.code
begin proc far
mov ax, @data
mov ds, ax
mov es, ax
mov ax, 0600h
call screen ;清屏
call curs ;设置光标
call openh ;打开文件,设置TABLE
cmp endcde, 0 ;打开错误吗?
jnz a0 ;错误,转结束
call in_Part ;没错,输入零件号和零件数量
a0: mov ax, 4c00h ;退出程序,返回DOS
int 21h
begin endp
;-------------------------------------------------------------
;打开文件
openh proc near
mov ah, 3dh
mov al, 0
lea dx, pathname
int 21h
jc bbb ;打开错误吗?
mov handle, ax ;没有错,保存文件代号

ret
bbb: mov endcde, 01 ;打开错误,指示结束处理
lea dx, opnmsg
call errm ;显示出错信息
ret
openh endp
;-------------------------------------------------------------
;读磁盘记录
readh proc near
mov ah, 3fh
mov bx, handle
mov cx, 19 ;准备读入的字节数
lea dx, table
int 21h
jc c1 ;读错误吗?
cmp ax, 0 ;文件已读完吗?
je c2 ;读完,退出
cmp table, 1ah ;文件结束符吗?
Je c2
mov bp, ax ;读成功则在AX中返回实际读入的字节数存入bp
ret
c1: mov endcde, 01 ;读错误或文件读完,指示结束处理
lea dx, readmsg ;读错误
call errm ;显示出错信息
jmp c3
c2: mov endcde, 02 ;读错误或文件读完,指示结束处理
c3: ret
readh endp
;-------------------------------------------------------------

;绝对移动文件读写指针
mov_pointer proc near
mov ah, 42h
mov al, 0
mov bx, handle
int 21h
jc d1 ;错误吗?
ret
d1: lea dx, movmsg ;错误
call errm ;显示出错信息
mov endcde, 01 ;错误,指示结束处理
ret
mov_pointer endp
;-------------------------------------------------------------
;输入零件号和零件数量
in_Part proc near
lea dx, in_mes1 ;显示提示信息,提示输入零件号
in_Part1: call input ;输入数据
cmp in_buffer+1, 3 ;输入的零件号个数是3位吗?
lea dx, out_mes2 ;显示提示信息,提示重新输入零件号
jne in_Part1
cld
mov cx, 0 ;位移量的高位字
mov dx, 0 ;位移量的低位字
call mov_pointer ;绝对移动文件读写指针到文件首
in_Part2: call readh ;读磁盘记录
cmp endcde, 2 ;读文件结束吗?
je in_Part1 ;结束,未找到对应的零件重新输入
cmp endcde, 1 ;读错误吗?

je in_Part4 ;错误,转结束
lea si, in_buffer+2 ;查找零件号对应的零件
lea di, table
mov cx, 3
repe cmpsb
je in_Part3 ;找到对应的零件
jmp in_Part2 ;找下一个零件
in_Part3: lea dx, in_mes2 ;显示提示信息,提示输入零件数量
call input ;输入数据
call dec_bin ;将输入数据转换为二进制数,在bx中
lea di, table ;di指向该记录的首地址
mov ax, [di+15] ;取单价
mul bx ;总价格在(dx),(ax)中
mov sum_price, ax
mov sum_price+2, dx
call disp_rec ;显示信息
in_Part4: ret
in_Part endp
;-------------------------------------------------------------
;输入数据
input proc near
input1: mov ah, 09h ;显示字符串
int 21h
mov ah, 0ah ;输入字符串
lea dx, in_buffer
int 21h
lea dx, out_mes1 ;显示提示信息
mov cl, in_buffer+1

cmp cl, 0 ;输入的数字个数为0吗?
jz input1
mov ch, 0
mov bx, 2
input2: mov al, in_buffer[bx] ;输入的是数字0~9吗?
cmp al, ‘0’
jb input1
cmp al, ‘9’
ja input1
inc bx
loop input2
ret
input endp
;-------------------------------------------------------------
;将十进制数转换为二进制数子程序
dec_bin proc near
mov bx, 0
mov si, 2
mov cl, in_buffer+1
mov ch, 0
transfer: mov al, in_buffer[si] ;从十进制的高位到低位取数
and al, 0fh ;将ascii码转换为十进制数
mov ah, 0
push cx
xchg ax, bx ;十进制数高位×10+低位 = 二进制数
mov cx, 10
mul cx
add bx, ax ;转换的二进制数在(bx)中
pop cx

inc si
loop transfer
ret
dec_bin endp
;-----------------------------------------------------------------
;显示记录
disp_rec proc near
call disp_crlf
lea dx, message ;显示标题
mov ah, 09h
int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 3 ;显示3位数的零件号
lea dx, table ;dx指向该记录的首地址
int 21h
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 12 ;显示12位的零件说明
lea dx, table ;dx指向该记录的首地址
add dx, 3
int 21h
lea dx, tackline ;显示输出“ | ”

mov ah, 09h
int 21h
call bin_dec ;总价格转换为十进制数显示
lea dx, tackline ;显示输出“ | ”
mov ah, 09h
int 21h
call disp_crlf
ret
disp_rec endp
;-----------------------------------------------------------------
;4字节二进制数转换为10进制子程序
bin_dec proc near
mov bx, 0 ;10字节的bcd码单元清0
mov cx, 10
bin_dec1: mov decimal[bx], 0
inc bx
loop bin_dec1
mov cx, 4*8 ;4字节二进制数共4*8=32位
bin_dec2: mov bx, 10-1 ;计算
(((a31*2+a30)*2+a29)...)*2+a0
shl word ptr [sum_price],1 ;4字节二进制数左移1位
rcl word ptr [sum_price +2],1
push cx
mov cx, 10
bin_dec3: mov al, decimal[bx] ;计算(...)*2+ai,ai由进位位带入
adc al, al
aaa ;非压缩bcd码加法调整
mov decimal[bx], al
dec bx

loop bin_dec3
pop cx
loop bin_dec2
call disp
ret
bin_dec endp
;--------------------------------------------------------------------------
disp proc near ;显示输出子程序
mov cx, 10
mov bx, 0
disp1: add decimal[bx], 30h ;变为ascii码
inc bx
loop disp1
mov cx, 10 ;下面5条指令是为了不显示数据左边的“0”
cld
lea di, decimal
mov al, 30h ;30h为“0”的ascii码
repe scasb
dec di
mov dx, di
mov ah, 09h
int 21h
ret
disp endp ;disp子程序结束
;---------------------------------------------------------------------------
;屏幕上卷
screen proc near ;入口参数为ax
mov bh, 1eh ;设置颜色
mov cx, 0 ;屏幕左上角

mov dx, 184fh ;屏幕右下角
int 10h
ret
screen endp
;-------------------------------------------------------------
;设置光标
curs proc near
mov ah, 2 ;设置光标
mov bh, 0
mov dh, 0 ;行号
mov dl, 0 ;列号
int 10h
ret
curs endp
;-------------------------------------------------------------
;显示出错信息
errm proc near
mov ah, 40h ;向标准输出设备(文件代号=01)写文件
mov bx, 01 ;标准输出设备的文件代号=01
mov cx, 20
int 21h
ret
errm endp
;-------------------------------------------------------------
disp_crlf proc near ;显示回车换行符子程序
lea dx, crlf
mov ah, 09h
int 21h
ret

disp_crlf endp ; disp_crlf子程序结束
; -----------------------------------------------------------
end begin

参考文章

http://blog.sina.com.cn/s/blog_77f58b350100q4dv.html

https://wenku.baidu.com/view/303e0e114431b90d6c85c720.html

https://shentuzhigang.blog.csdn.net/article/details/106560578

《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第十一章——自编解析与答案相关推荐

  1. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第二章——自编解析与答案

    2.1 在80x86微机的输入/输出指令中,I/O端口号通常是由DX寄存器提供的,但有时也可以在指令中直接指定00~FFH的端口号.试问可直接由指令指定的I/O端口数. 解析: P31-2.5 外部设 ...

  2. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第一章——自编解析与答案

    1.1 用降幂法和除法将下列十进制数转换为二进制数和十六进制数: (1) 369   (2) 10000   (3) 4095   (4) 32767 解析: P4-1.1.3 十六进制数及其与二进制 ...

  3. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第十章——自编解析与答案

    10.1 写出指令,选择显示方式10H,并将背景设为绿色. 答: MOV AH, 00H MOV AL, 10H :选择显示方式10H(16色图形) INT 10H MOV AH, 10H MOV A ...

  4. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第八章——自编解析与答案

    8.1 写出分配给下列中断类型号在中断向量表中的物理地址. (1) INT 12H (2) INT 8 答:(1) 中断类型号12H在中断向量表中的物理地址为00048H.00049H.0004AH. ...

  5. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——自编解析与答案

    <IBM-PC汇编语言程序设计>(第2版)[沈美明 温冬婵]--第一章--自编解析与答案 <IBM-PC汇编语言程序设计>(第2版)[沈美明 温冬婵]--第二章--自编解析与答 ...

  6. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】答案

    内容修订.解析.扩展: <IBM-PC汇编语言程序设计>(第2版)[沈美明 温冬婵]--自编解析与答案 第 一 章. 习 题 1.1 用降幂法和除法将下列十进制数转换为二进制数和十六进制数 ...

  7. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第六章——自编解析与答案

    6.1 下面的程序段有错吗?若有,请指出错误. CRAY PROC PUSH AX ADD AX, BX RET ENDP CRAY 答:程序有错.改正如下: CRAY PROC ADD AX, BX ...

  8. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第五章——自编解析与答案

    5.1 试编写一个汇编语言程序,要求对键盘输入的小写字母用大写字母显示出来. 答:程序段如下: BEGIN: MOV AH, 1 :从键盘输入一个字符的DOS调用 INT 21H CMP AL, 'a ...

  9. 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第三章——自编解析与答案

    3.1 给定(BX)=637DH,(SI)=2A9BH,位移量D=7237H,试确定在以下各种寻址方式下的有效地址是什么? (1) 立即寻址 (2) 直接寻址 (3) 使用BX的寄存器寻址 (4) 使 ...

最新文章

  1. html5下拉智能,HTML5新增标签 + 智能表单
  2. 2018~2019-11 20165107 网络对抗技术期末免考 Exp10 Final Powershell学习应用与渗透实践...
  3. 【HDU - 5014】Number Sequence(贪心构造)
  4. RHEL6上课笔记之background_process_command
  5. pve安装黑群晖直通硬盘_蜗牛星际装机教程篇三:手把手教你安装黑群晖NAS
  6. android supportv4最新版本19.1,Android Studio:无法找到:’com.android.support:support-v4:19.1.0′...
  7. [leetcode]1.Two Sum
  8. 工作总结 项目中如何处理重复提交问题
  9. 2019年9月全国程序员工资统计(参考)
  10. 暑假第一战——java+mysql 个人信息管理系统
  11. 计算机算法设计与分析 第5版 (王晓东) 课后答案[解析]
  12. 左耳朵耗子:云原生的正确打开方式
  13. mac端锐捷无法验证服务器,还在为mac无法用锐捷认证校园网登陆而郁闷吗?
  14. 公司/组织苹果开发者账号申请流程
  15. BOF图像特征词典的原理以及实际测试
  16. 金笛全新技术架构,鲲鹏击浪从兹始
  17. 深圳市工业和信息化局关于征集创新产品的通知
  18. 如何在Win10日历便签中设置添加定时提醒和活动
  19. Windows server 2016 AD域的安装和升级域控制器
  20. 竣达技术 | 蓄电池内阻在线监测及告警方案

热门文章

  1. [论文泛读]Web服务组合综述相关论文1(3篇)
  2. 2给我背书_让优秀的人做你的背书人
  3. Myeclipse创建Maven项目提示:Creating maven-archetype-webapp has encountered a problem. 解决方法
  4. druid.io mysql 配置_druid.io 使用mysql存储metadata overlord启动出错
  5. linux 空格函数,linux c语言的split函数和空格处理函数
  6. jquery function_前端基础进阶(十三)详细图解jQuery扩展jQuery插件
  7. 线性代数中的矩阵消元法,求逆
  8. 为了OFFER,菜鸟的我必须搞懂动态规划系列三个背包问题之多重背包(二进制优化方法)
  9. 深度学习作业(一)手写字体
  10. Java web项目报错 Java compiler level does not match the version of the installed Java project facet.