《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第十一章——自编解析与答案
11.1 寫出文件代號式磁盤存取操作的錯誤代碼:
(1) 非法文件代號 (2) 路徑未發(fā)現(xiàn) (3) 寫保護磁盤
答:錯誤代碼為:
(1) 06 (2) 03 (4) 19
11.2 使用3CH功能建立一文件,而該文件已經(jīng)存在,這時會發(fā)生什么情況?
答:此操作將文件長度置為0,寫新文件,原文件內(nèi)容被清除。
11.3 從緩沖區(qū)寫信息到一個文件,如果沒有關閉文件,可能會出現(xiàn)什么問題?
答:文件結(jié)尾的部分信息就沒有被寫入磁盤,從而造成寫入的文件不完整。
11.4 下面的ASCIZ串有什么錯誤?
PATH_NAME DB ‘C:\PROGRAMS\TEST.DAT’
答:此ASCIZ串的最后少了一個全0字節(jié),應改為:
PATH_NAME DB ‘C:\PROGRAMS\TEST.DAT’, 0
11.5 下面為保存文件代號定義的變量有什么錯誤?
FILE_HNDL DB ?
答:文件代號是字類型,因此應改為:
FILE_HNDL DW ?
11.6 在ASCPATH字節(jié)變量中為驅(qū)動器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 ;所有的字節(jié)都寫入了嗎?
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 ;結(jié)束處理指示
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 ;錯誤,轉(zhuǎn)結(jié)束
contin: call readh ;讀磁盤記錄
cmp endcde, 0 ;讀錯誤嗎?
jnz a0 ;錯誤,轉(zhuǎn)結(jié)束
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 ;打開錯誤,指示結(jié)束處理
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 ;讀錯誤或文件讀完,指示結(jié)束處理
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 ;入口參數(shù)為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碼轉(zhuǎn)換為二進制數(shù)。下面是
輸入的例子:
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 ;最大輸入長度,輸入字符串功能的緩沖區(qū)
actlen db ? ;實際輸入長度
buffer db 13 DUP (' ') ;輸入字符串緩沖區(qū)
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 ;錯誤,轉(zhuǎn)結(jié)束
contin: call proch ;記錄處理
cmp actlen, 0 ;輸入的字符串長度為0,結(jié)束輸入嗎?
jne contin ;不結(jié)束,繼續(xù)
call clseh ;結(jié)束輸入,關閉文件
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 ;沒有輸入,結(jié)束
lea dx, prompt2 ;輸入零件名稱
mov bx, 12 ;零件名稱最多12個字符
call in_proc
jc exit ;沒有輸入,結(jié)束
lea dx, prompt3 ;輸入單價
mov bx, 5 ;零件單價最多5個十進制字符(相當于一個二進制字)
call in_proc
call dec_bin ;將十進制的單價轉(zhuǎn)換為二進制的單價
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 ;實際輸入字符數(shù)=0,則沒有輸入,結(jié)束
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緩沖區(qū)內(nèi)容送入dta
mov cx, bx
rep movsb ;將輸入內(nèi)容送入dta
clc ;有輸入字符,返回(cf)=0
jmp in_end
end_in: stc ;沒有輸入字符,返回(cf)=1
in_end: ret
in_proc endp
;-----------------------------------------------------------------
;將十進制的單價轉(zhuǎn)換為二進制的單價子程序
dec_bin proc near
mov bx, 0
mov si, 0
mov cx, 5
transfer: mov al, buffer[si] ;從十進制的高位到低位取數(shù)
cmp al, 0dh ;是回車嗎?
je dec_bin1
cmp al, ' ' ;是空格嗎?
je dec_bin1
and al, 0fh ;將ascii碼轉(zhuǎn)換為十進制數(shù)
mov ah, 0
push cx
xchg ax, bx ;十進制數(shù)高位×10+低位 = 二進制數(shù)
mov cx, 10
mul cx
xchg ax, bx
add bx, ax ;轉(zhuǎn)換的二進制數(shù)在(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 ;寫文件結(jié)束符1ah
call writh
mov ah, 3eh
mov bx, handle
int 21h
ret
clseh endp
;-------------------------------------------------------------
;屏幕上卷
scren proc near ;入口參數(shù)為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子程序結(jié)束
; -----------------------------------------------------------
end begin ;匯編語言源程序結(jié)束
11.10 編寫一個程序使用文件代號式讀出并顯示11.9題建立的文件。注意,要把二進制數(shù)表示的單價轉(zhuǎn)換為
ASCII碼。
答:用文件代號式讀出并顯示文件,程序如下:
TITLE HANDREAD.EXE ;利用文件代號式順序讀并顯示文件程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h
.data
endcde db 0 ;結(jié)束處理指示
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 ;錯誤,轉(zhuǎn)結(jié)束
contin: call readh ;讀磁盤記錄
cmp endcde, 0 ;讀錯誤嗎?
jnz a0 ;錯誤,轉(zhuǎn)結(jié)束
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 ;打開錯誤,指示結(jié)束處理
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 ;文件結(jié)束符嗎?
Je c2
ret
c1: lea dx, opnmsg ;讀錯誤
call errm ;顯示出錯信息
c2: mov endcde, 01 ;讀錯誤或文件讀完,指示結(jié)束處理
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 ;轉(zhuǎn)換為十進制數(shù)顯示
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
;-----------------------------------------------------------------
;將二進制的單價轉(zhuǎn)換為十進制的單價并顯示子程序
bin_dec proc near
push cx
mov cx, 10000d
call dec_div ;調(diào)除法并顯示輸出子程序
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 ;余數(shù)保存在(si)中作下一次的除法
mov dl, al ;商(在00h~09h范圍內(nèi))送(dl)
add dl, 30h ;轉(zhuǎn)換為0~9的ascii碼
mov ah, 02h ;顯示輸出
int 21h
ret
dec_div endp
;-----------------------------------------------------------------
;屏幕上卷
screen proc near ;入口參數(shù)為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子程序結(jié)束
; -----------------------------------------------------------
end begin
11.11 對11.9題建立的文件按下面的要求編寫程序:
(1) 把所有的記錄讀入內(nèi)存的數(shù)據(jù)緩沖區(qū)TABLE;
(2) 顯示字符串提示用戶輸入零(配)件號及其數(shù)量;
(3) 按零件搜索TABLE;
(4) 如果發(fā)現(xiàn)所要求的零件,用它的單價計算出總價(單價×數(shù)量);
(5) 顯示零(配)件說明及總價值。
答:程序如下:
TITLE READ11.EXE ;利用文件代號式讀并計算顯示程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h
.data
endcde db 0 ;結(jié)束處理指示
pathname db 'filename.lst', 0
in_mes1 db '請輸入3位數(shù)的零件號Part#:', '$'
in_mes2 db '請輸入該零件的數(shù)量:', '$'
out_mes1 db '輸入的不是數(shù)字!請重新輸入數(shù)字:’, '$'
out_mes2 db '輸入的零件號不存在!請重新輸入3位數(shù)的零件號Part#:', '$'
in_buffer db 6, ?, 6 dup(20h) ;輸入緩沖區(qū)
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 ;錯誤,轉(zhuǎn)結(jié)束
call readh ;讀磁盤記錄
cmp endcde, 0 ;讀錯誤嗎?
jnz a0 ;錯誤,轉(zhuǎn)結(jié)束
call in_Part ;沒錯,輸入零件號和零件數(shù)量
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 ;打開錯誤,指示結(jié)束處理
lea dx, opnmsg
call errm ;顯示出錯信息
ret
openh endp
;-------------------------------------------------------------
;讀磁盤記錄
readh proc near
mov ah, 3fh
mov bx, handle
mov cx, 19*100 ;準備讀入的字節(jié)數(shù)
lea dx, table
int 21h
jc c1 ;讀錯誤嗎?
cmp ax, 0 ;文件已讀完嗎?
je c2 ;讀完,退出
cmp table, 1ah ;文件結(jié)束符嗎?
Je c2
mov bp, ax ;讀成功則在AX中返回實際讀入的字節(jié)數(shù)存入bp
ret
c1: lea dx, readmsg ;讀錯誤
call errm ;顯示出錯信息
c2: mov endcde, 01 ;讀錯誤或文件讀完,指示結(jié)束處理
ret
readh endp
;-------------------------------------------------------------
;輸入零件號和零件數(shù)量
in_Part proc near
lea dx, in_mes1 ;顯示提示信息,提示輸入零件號
in_Part1: call input ;輸入數(shù)據(jù)
cmp in_buffer+1, 3 ;輸入的零件號個數(shù)是3位嗎?
lea dx, out_mes2 ;顯示提示信息,提示重新輸入零件號
jne in_Part1
cld
mov ax, bp ;取實際讀入文件的字節(jié)數(shù)
mov cl, 19 ;每個記錄的長度為19個字符
div cl ;計算實際讀取的記錄數(shù)在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 ;顯示提示信息,提示輸入零件數(shù)量
call input ;輸入數(shù)據(jù)
call dec_bin ;將輸入數(shù)據(jù)轉(zhuǎn)換為二進制數(shù),在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
;-------------------------------------------------------------
;輸入數(shù)據(jù)
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 ;輸入的數(shù)字個數(shù)為0嗎?
jz input1
mov ch, 0
mov bx, 2
input2: mov al, in_buffer[bx] ;輸入的是數(shù)字0~9嗎?
cmp al, ‘0’
jb input1
cmp al, ‘9’
ja input1
inc bx
loop input2
ret
input endp
;-------------------------------------------------------------
;將十進制數(shù)轉(zhuǎn)換為二進制數(shù)子程序
dec_bin proc near
mov bx, 0
mov si, 2
mov cl, in_buffer+1
mov ch, 0
transfer: mov al, in_buffer[si] ;從十進制的高位到低位取數(shù)
and al, 0fh ;將ascii碼轉(zhuǎn)換為十進制數(shù)
mov ah, 0
push cx
xchg ax, bx ;十進制數(shù)高位×10+低位 = 二進制數(shù)
mov cx, 10
mul cx
add bx, ax ;轉(zhuǎn)換的二進制數(shù)在(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位數(shù)的零件號
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 ;總價格轉(zhuǎn)換為十進制數(shù)顯示
lea dx, tackline ;顯示輸出“ | ”
mov ah, 09h
int 21h
call disp_crlf
ret
disp_rec endp
;-----------------------------------------------------------------
;4字節(jié)二進制數(shù)轉(zhuǎn)換為10進制子程序
bin_dec proc near
mov bx, 0 ;10字節(jié)的bcd碼單元清0
mov cx, 10
bin_dec1: mov decimal[bx], 0
inc bx
loop bin_dec1
mov cx, 4*8 ;4字節(jié)二進制數(shù)共4*8=32位
bin_dec2: mov bx, 10-1 ;計算
(((a31*2+a30)*2+a29)...)*2+a0
shl word ptr [sum_price],1 ;4字節(jié)二進制數(shù)左移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碼加法調(diào)整
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 ;變?yōu)閍scii碼
inc bx
loop disp1
mov cx, 10 ;下面5條指令是為了不顯示數(shù)據(jù)左邊的“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子程序結(jié)束
;---------------------------------------------------------------------------
;屏幕上卷
screen proc near ;入口參數(shù)為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子程序結(jié)束
; -----------------------------------------------------------
end begin
11.12 用隨機處理記錄的方式編寫程序,將用戶需要的零(配)件記錄讀取到TABLE,并根據(jù)鍵入的數(shù)量,計
算出總價值,然后顯示出零(配)件說明及總價值。
答:程序如下:
TITLE READ_RAN.EXE ;利用文件代號式隨機讀并計算顯示程序
;Read disk records created by hancreat
;-------------------------------------------------------------
.model small
.stack 100h
.data
endcde db 0 ;結(jié)束處理指示
pathname db 'filename.lst', 0
in_mes1 db '請輸入3位數(shù)的零件號Part#:', '$'
in_mes2 db '請輸入該零件的數(shù)量:', '$'
out_mes1 db '輸入的不是數(shù)字!請重新輸入數(shù)字:’, '$'
out_mes2 db '輸入的零件號不存在!請重新輸入3位數(shù)的零件號Part#:', '$'
in_buffer db 6, ?, 6 dup(20h) ;輸入緩沖區(qū)
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 ;錯誤,轉(zhuǎn)結(jié)束
call in_Part ;沒錯,輸入零件號和零件數(shù)量
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 ;打開錯誤,指示結(jié)束處理
lea dx, opnmsg
call errm ;顯示出錯信息
ret
openh endp
;-------------------------------------------------------------
;讀磁盤記錄
readh proc near
mov ah, 3fh
mov bx, handle
mov cx, 19 ;準備讀入的字節(jié)數(shù)
lea dx, table
int 21h
jc c1 ;讀錯誤嗎?
cmp ax, 0 ;文件已讀完嗎?
je c2 ;讀完,退出
cmp table, 1ah ;文件結(jié)束符嗎?
Je c2
mov bp, ax ;讀成功則在AX中返回實際讀入的字節(jié)數(shù)存入bp
ret
c1: mov endcde, 01 ;讀錯誤或文件讀完,指示結(jié)束處理
lea dx, readmsg ;讀錯誤
call errm ;顯示出錯信息
jmp c3
c2: mov endcde, 02 ;讀錯誤或文件讀完,指示結(jié)束處理
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 ;錯誤,指示結(jié)束處理
ret
mov_pointer endp
;-------------------------------------------------------------
;輸入零件號和零件數(shù)量
in_Part proc near
lea dx, in_mes1 ;顯示提示信息,提示輸入零件號
in_Part1: call input ;輸入數(shù)據(jù)
cmp in_buffer+1, 3 ;輸入的零件號個數(shù)是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 ;讀文件結(jié)束嗎?
je in_Part1 ;結(jié)束,未找到對應的零件重新輸入
cmp endcde, 1 ;讀錯誤嗎?
je in_Part4 ;錯誤,轉(zhuǎn)結(jié)束
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 ;顯示提示信息,提示輸入零件數(shù)量
call input ;輸入數(shù)據(jù)
call dec_bin ;將輸入數(shù)據(jù)轉(zhuǎn)換為二進制數(shù),在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
;-------------------------------------------------------------
;輸入數(shù)據(jù)
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 ;輸入的數(shù)字個數(shù)為0嗎?
jz input1
mov ch, 0
mov bx, 2
input2: mov al, in_buffer[bx] ;輸入的是數(shù)字0~9嗎?
cmp al, ‘0’
jb input1
cmp al, ‘9’
ja input1
inc bx
loop input2
ret
input endp
;-------------------------------------------------------------
;將十進制數(shù)轉(zhuǎn)換為二進制數(shù)子程序
dec_bin proc near
mov bx, 0
mov si, 2
mov cl, in_buffer+1
mov ch, 0
transfer: mov al, in_buffer[si] ;從十進制的高位到低位取數(shù)
and al, 0fh ;將ascii碼轉(zhuǎn)換為十進制數(shù)
mov ah, 0
push cx
xchg ax, bx ;十進制數(shù)高位×10+低位 = 二進制數(shù)
mov cx, 10
mul cx
add bx, ax ;轉(zhuǎn)換的二進制數(shù)在(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位數(shù)的零件號
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 ;總價格轉(zhuǎn)換為十進制數(shù)顯示
lea dx, tackline ;顯示輸出“ | ”
mov ah, 09h
int 21h
call disp_crlf
ret
disp_rec endp
;-----------------------------------------------------------------
;4字節(jié)二進制數(shù)轉(zhuǎn)換為10進制子程序
bin_dec proc near
mov bx, 0 ;10字節(jié)的bcd碼單元清0
mov cx, 10
bin_dec1: mov decimal[bx], 0
inc bx
loop bin_dec1
mov cx, 4*8 ;4字節(jié)二進制數(shù)共4*8=32位
bin_dec2: mov bx, 10-1 ;計算
(((a31*2+a30)*2+a29)...)*2+a0
shl word ptr [sum_price],1 ;4字節(jié)二進制數(shù)左移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碼加法調(diào)整
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 ;變?yōu)閍scii碼
inc bx
loop disp1
mov cx, 10 ;下面5條指令是為了不顯示數(shù)據(jù)左邊的“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子程序結(jié)束
;---------------------------------------------------------------------------
;屏幕上卷
screen proc near ;入口參數(shù)為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子程序結(jié)束
; -----------------------------------------------------------
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
總結(jié)
以上是生活随笔為你收集整理的《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第十一章——自编解析与答案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《IBM-PC汇编语言程序设计》(第2版
- 下一篇: 《IBM-PC汇编语言程序设计》(第2版