课程设计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