課程設計1(p211)、
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
課程設計1(p211)
# 執行結果
# code
; DATE: 20190614
; DESCRIPTION: 在屏幕上按格式顯示數據
assume cs:code
data segment
db 16 dup (0) ; 用於臨時保存數據轉字符串的結果
; 年份
db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983'
db '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992'
db '1993', '1994', '1995'
; 收入
dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97497, 140417, 197514
dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000
; 僱員
dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, 0 ; ds:si 指向data段中的自定義字符串空間
call company
mov ax, 4c00H
int 21H
; 數據處理並顯示
company:
push ax
push bx
push cx
push dx
push si
push di ; 保護現場
mov bx, 16 ; ds:bx 指向年份
mov di, 16
add di, 168 ; ds:di 指向僱員
mov dh, 2 ; 屏幕上顯示行
mov cx, 21 ; 一共要顯示21行數據
year:
push cx ; 顏色cl將覆蓋cx
mov dl, 10 ; 屏幕上顯示列
mov cl, 2 ; 顏色
; 年份
mov ax, [bx]
mov [si], ax
mov ax, [bx+2]
mov [si+2], ax ; 直接將4Bytes年份複製到ds:si
mov ax, 0
mov [si+4], ax ; 字符串以0結尾
call show_str
; 收入
push dx ; div中dx爲被除數高16位
mov ax, [bx+84] ; ax存放被除數低16位
mov dx, [bx+86] ; dx存放被除數高16位
call ddtoc
pop dx
add dl, 10 ; 屏幕上顯示列右移10列
call show_str
; 僱員
mov ax, [di] ; ax存放16位的被除數
call dtoc
add dl, 15 ; 屏幕上顯示列右移15列
call show_str
; 人均收入
push dx ; div指令用dx存儲餘數
mov ax, [bx+84] ; ax存放被除數低16位
mov dx, [bx+86] ; dx存放被除數高16位
div word ptr [di]
pop dx
call dtoc ; 結果的商存放在ax中
add dl, 10 ; 屏幕上顯示列右移10列
call show_str
pop cx
inc dh ; 屏幕上顯示行下移一行
add bx, 4 ; 下一個年份和收入數據
add di, 2 ; 下一個僱員數據
loop year
pop di
pop si
pop dx
pop cx
pop bx
pop ax ; 恢復現場
ret ; 返回
; 名稱:dtoc
; 功能:將word型數據轉變爲表示十進制數的字符串,以0結尾
; 參數:(ax)=word型數據,ds:si指向字符串的首地址
; 返回:無
dtoc:
push ax
push bx
push cx
push dx
push si
mov bx, 10
division:
mov dx, 0 ; 被除數的高16位
div bx
add dx, 30H ; dx爲餘數,轉爲字符
push dx ; 餘數入棧
inc si ; 通過si統計長度
mov cx, ax ; ax爲商
jcxz save0
jmp short division
save0:
mov cx, si
mov si, 0
s2:
pop [si] ; 餘數出棧,保存到ds:si
inc si ; 取巧,出棧2Bytes,但si+1;末尾以0結尾
loop s2
pop si
pop dx
pop cx
pop bx
pop ax
ret
; 名稱:ddtoc
; 功能:將dword型數據轉變爲表示十進制數的字符串,以0結尾
; 參數:(ax)=dword低16位,(dx)=dowrd高16位,ds:si指向字符串的首地址
; 返回:無
ddtoc:
push ax
push cx
push dx
push si
push di
mov di, 0
change:
mov cx, 10 ; cx爲除數
call divdw
add cx, 30H ; cx爲餘數, 加48轉爲字符
push cx ; 餘數入棧
inc di ; 通過di統計餘數個數
mov cx, ax
or cx, dx ; 判斷商是否爲0
jcxz save
jmp short change
save:
mov cx, di
s1:
pop [si] ; 餘數出棧,保存到ds:si
inc si ; 取巧,出棧2Bytes,但si+1;末尾以0結尾
loop s1
pop di
pop si
pop dx
pop cx
pop ax
ret
; 名稱:divdw
; 功能:不會產生溢出的除法,被除數爲dword,除數爲word,結果爲dword
; 參數:(ax)=dword低16位 (dx)=dword高16位 (cx)=除數
; 返回:(dx)=結果高16位 (ax)=結果低16位 (cx)=餘數
divdw:
push bx ; ax cx dx爲返回值
push ax ; 被除數低16位
; 被除數的高16位除法
mov ax, dx
mov dx, 0
div cx
; 被除數的低16位除法
mov bx, ax ; 高16位除法的商暫移到bx
pop ax
div cx
; 結果返回
mov cx, dx ; 低16位除法的餘數移到cx
mov dx, bx ; 高16位除法的商移到dx
pop bx
ret
; 名稱:show_str
; 功能:在指定的位置,用指定的顏色,顯示一個用0結束的字符串
; 參數:(dh)=行號(取值範圍0~24),(dl)=列號(取值範圍0~79)
; (cl)=顏色, ds:si指向字符串首地址
; 返回:無
show_str:
push ax
push cx
push dx
push si
push di
push es
mov ax, 0b800H
mov es, ax ; 顯示緩衝區 b8000 ~ b8ffff
mov al, 160 ; 一行80個字符,加上顏色屬性,佔160Bytes
mul dh ; 乘以行號
mov di, ax
mov al, 2 ; 內容1Byte、屬性1Byte
mul dl ; 乘以列號
add di, ax ; es:di指向屏幕指定位置對應的顯示緩衝區
mov ah, cl ; 高位字節存儲顏色屬性
s0:
mov ch, 0
mov cl, [si] ; 給定的字符串以0結尾
jcxz ok
mov al, cl ; 低位字節存儲字符ASCII碼
mov es:[di], ax
inc si ; 下一個字符
add di, 2 ; 屏幕顯示位置右移2Bytes
jmp short s0
ok:
pop es
pop di
pop si
pop dx
pop cx
pop ax
ret
code ends
end start