任务:将实验 7 中的 Power idea 公司的数据按照下图所示的格式在屏幕上输出出来。
写于毕业后的第一个夏日:
assume cs:code
data segment
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,97479,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:
;初始化各寄存器
initReg:
mov ax,data ;使ds指向data段
mov ds,ax
mov bx,0 ;bx用于定位年份段、总收入段、人数段的起始位置
mov si,0 ;si用于定位各段中第几个数据
mov ax,0b800h ;使es指向显示缓冲区的段地址
mov es,ax
mov bp,0 ;bp用于定位显示缓冲区中第几列的起始地址
mov di,0 ;di用于定位显示缓冲区中某列的待写入数据的偏移地址
mov ax,0
mov dx,0
mov cx,0
;用于设置显示的起始位置(行、列)和字符颜色
config:
;(al)=字符的颜色
mov ah,07h
;(dh)=起始行(0~24)
mov dh,2
;(dl)=起始列(0~79)
mov dl,5
;主程序,按行输出数据至屏幕
mov cx,21 ;总共21年的数据,故循环21次输出
mainProcess:
;--------------------------------------------------------------------------------
;显示年份
show_year:
push ax
push bx
push si
;计算该次循环年份的偏移位置
push ax
mov ax,4
mul si
mov si,ax
pop ax
mov al,ds:[bx+si] ;将年份的千位输出至屏幕
mov es:[bp+di],ax
add di,2
mov al,ds:[bx+si+1] ;将年份的百位输出至屏幕
mov es:[bp+di],ax
add di,2
mov al,ds:[bx+si+2] ;将年份的十位输出至屏幕
mov es:[bp+di],ax
add di,2
mov al,ds:[bx+si+3] ;将年份的个位输出至屏幕
mov es:[bp+di],ax
mov di,0 ;将di的偏移地址置为0
pop si
pop bx
pop ax
;--------------------------------------------------------------------------------
;显示公司当年年收入
push ax
push bx
push cx
push si
annual_income:
;计算该次循环年收入的偏移位置
push ax
mov ax,4
mul si
mov si,ax
pop ax
add bp,14h ;各列之间间隔10个字节的空间
mov bx,54h ;使bx指向年收入段的起始地址
call dtoc_dd
mov di,0 ;将di的偏移地址置为0
pop si
pop cx
pop bx
pop ax
;--------------------------------------------------------------------------------
;显示公司当年人数
push ax
push bx
push cx
push si
show_numbers:
;计算该次循环公司人数的偏移位置
push ax
mov ax,2
mul si
mov si,ax
pop ax
add bp,14h ;各列之间间隔10个字节的空间
mov bx,0A8h ;使bx指向公司人数段的起始地址
call dtoc_dw
mov di,0 ;将di的偏移地址置为0
pop si
pop cx
pop bx
pop ax
;--------------------------------------------------------------------------------
;计算并显示公司当年人均收入
push ax
push bx
push cx
add bp,14h ;各列之间间隔10个字节的空间
average_salary:
;获取该年公司年收入
mov bx,54h ;使bx指向年收入段的起始地址
push si
;计算该次循环年收入的偏移位置
push ax
mov ax,4
mul si
mov si,ax
pop ax
mov ax,ds:[bx+si] ;从ds:[bx+si]处获取该年公司年收入的低16位
mov dx,ds:[bx+si+2] ;从ds:[bx+si+2]处获取该年公司年收入的高16位
pop si
push si
;获取该年公司人数
mov bx,0A8h ;使bx指向公司人数段的起始地址
;计算该次循环公司人数的偏移位置
push ax
push dx
mov ax,2
mul si
mov si,ax
pop dx
pop ax
mov cx,ds:[bx+si] ;从ds:[bx+si]处获取该年公司人数
call divdw
call show_str
pop si
mov di,0 ;将di的偏移地址置为0
pop cx
pop bx
pop ax
inc si
add bp,64h
loop mainProcess
mov ax,4c00h
int 21h
;以下部分为子程序
;---------------------------------------------------------------------------------
;dtoc_dd
;功能:将数字转化为对应的ASCII码,并通过调用子程序show_str显示到屏幕上
;参数:ds:si指向待处理的数字的首地址
;返回值:无
dtoc_dd:
push ax
push bx
push si
mov ax,ds:[bx+si]
mov dx,ds:[bx+si+2]
mov bx,0 ;bx用于统计该数值的位数
dtoc_dd_main:
mov cx,10
call divdw
add cl,30h ;将数字转为对应的ASCII码
mov ch,07h ;设置颜色
push cx
mov cx,ax
inc bx
jcxz dtoc_dd_write ;判断(cx)是否等于0,若等于0,则说明该数值已转换完,跳至dtoc_dd_end
jmp dtoc_dd_main
dtoc_dd_write:
mov cx,bx
dtoc_dd_write_s0:
pop es:[bp+di] ;写入显示缓冲区
add di,2
loop dtoc_dd_write_s0
dtoc_dd_end:
pop si
pop bx
pop ax
ret
;dtoc_dw
;功能:将数字转化为对应的ASCII码,并通过调用子程序show_str显示到屏幕上
;参数:ds:si指向待处理的数字的首地址
;返回值:无
dtoc_dw:
push bx
mov ax,ds:[bx+si]
mov dx,0
mov bx,0 ;bx用于统计该数值的位数
dtoc_dw_main:
mov cx,10
call divdw
add cl,30h ;将数字转为对应的ASCII码
mov ch,07h ;设置颜色
push cx
mov cx,ax
inc bx
jcxz dtoc_dw_write ;判断(cx)是否等于0,若等于0,则说明该数值已转换完,跳至dtoc_dw_write
jmp dtoc_dw_main
dtoc_dw_write:
mov cx,bx
dtoc_dw_write_s0:
pop es:[bp+di] ;写入显示缓冲区
add di,2
loop dtoc_dw_write_s0
dtoc_dw_end:
pop bx
ret
;show_str
;功能:将栈中的ASCII码输出至屏幕
;参数:行列位置,颜色,ASCII码的个数
;返回值:无
show_str:
push bx
mov bx,0 ;bx用于统计该数值的位数
show_str_main:
mov cx,10
call divdw
add cl,30h ;将数字转为对应的ASCII码
mov ch,07h ;设置颜色
push cx
mov cx,ax
inc bx
jcxz show_str_write
jmp show_str_main
show_str_write:
mov cx,bx
show_str_write_s0:
pop es:[bp+di] ;写入显示缓冲区
add di,2
loop show_str_write_s0
show_str_end:
pop bx
ret
;divdw
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位
; (cx)=余数
divdw:
push bx
push ax
mov ax,dx
mov dx,0
div cx
mov bx,ax
pop ax
div cx
mov cx,dx
mov dx,bx
pop bx
ret
code ends
end start
写于大二:
assume cs:code
data segment
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,97479,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: call codun
mov ax,4c00h
int 21h
codun: mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
mov bx,0
mov si,0
mov di,0
mov bp,0
adress:mov dl,5
mov dh,5
dec dh
mov al,0a0h
mul dh
mov cx,ax
dec dl
mov al,2h
mul al
add ax,cx
mov di,ax
mov cx,21
print:push di ;4
push cx ;2
push si ;3
mov cx,4
mov dl,2h
push di ;5
;year
year:
mov al,ds:[bx+si]
mov es:[bp+di],al
mov es:[bp+di+1],dl
inc si
add di,2
loop year
pop di ;5
;add di,10 ;列间距
pop si ;3
add bx,54h
;t_sala
t_sala:push di ;6
add di,18 ;起始位置
mov ax,ds:[bx+si]
mov dx,ds:[bx+si+2]
call ddtoc ;转化并调用show_str,注意 di的指向
add bx,54h
;add di,10 ;列间距
pop di ;6
;t_num
t_num: push di ;7
add di,42
push si ;1
call get_si ;取得si的值
mov ax,ds:[bx+si]
sub dx,dx ;注意此时di的值
call dwtoc ;转化并调用show_str
;add di,10 ;列间距
pop ax
pop di ;7
push ax
;p_sala
p_sala:add di,62
mov cx,ds:[bx+si]
sub bx,54h
pop si ;1
mov ax,ds:[bx+si]
mov dx,ds:[bx+si+2]
call divdd ;取得结果并调用show_str
sub bx,bx
add si,4
pop cx ;2
add bp,0a0h ;指向下一行
pop di ;4 使di指向起始点
loop print
;子程序
;get_si
get_si:sub dx,dx
mov ax,si
mov cx,2
div cx
sub dx,dx
mov ah,0
mov si,ax
ret
;ddtoc
ddtoc: push bx
push si
sub si,si ;清零,用以计数据的位数
lp_dd: mov cx,dx
jcxz to_div
mov cx,0ah
push ax
mov ax,dx
sub dx,dx
div cx
mov bx,ax
pop ax
push bx
div cx
mov cx,dx
pop dx
push cx ;余数
inc si ;计数
jmp short lp_dd
to_div:mov cx,0ah
div cx
mov cx,ax
push dx ;余数
inc si ;计数
jcxz out_dd
mov cx,dx
sub dx,dx
jmp short to_div
out_dd:call show_str
pop si
pop bx
ret
;show_str
show_str:sub dx,dx
mov dl,2h
mov cx,si
pop si
lp_str:pop ax
add al,30h
mov es:[bp+di],al
mov es:[bp+di+1],dl
add di,2
loop lp_str
push si
add di,2
ret
;dwtoc
dwtoc: push bx
push si
sub si,si
lp_dw: mov cx,0ah
div cx
mov cx,ax
push dx
inc si
jcxz out_dw
sub dx,dx
jmp short lp_dw
out_dw: call show_str
pop si
pop bx
ret
;divdd
divdd: push bx
push si
sub si,si
div cx
sub dx,dx
call dwtoc
pop si
pop bx
ret
code ends
end start