题目:
汇编代码:
assume cs:codesg
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'
;以上是表示21年的21个字符串
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型数据
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
table segment
db 21 dup ('year sumn ne ?? ')
table ends
data_string segment
db 10 dup (0)
data_string ends
stack segment
db 16 dup (0)
stack ends
codesg segment
start:
;################之前的那个代码##################
mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov di,0
mov bx,0
mov si,0
mov cx,21
s:
;复制年份 year
mov ax,[si]
mov es:[bx],ax
mov ax,[si+2]
mov es:[bx+2],ax
;复制总收入 summ
mov ax,[si+84]
mov es:[bx+5],ax
mov dx,[si+84+2];高位直接存在dx
mov es:[bx+5+2],dx
;复制雇员人数 ne
mov bp,[di+168]
mov es:[bx+10],bp
div word ptr es:[bx+10]
;商,余数在dx中
mov es:[bx+13],ax
add bx,16
add si,4
add di,2
loop s
;################################################
;################新增加显示在屏幕上##############
;##################写成四个循环##################
mov ax,data_string
mov ds,ax
mov si,0 ;ds:[si]指向字符串首地址
mov ax,stack
mov ss,ax
mov sp,10H
mov di,1
mov bx,0
mov cx,21
year:
push cx
mov si,0
mov cx,4
s_year:
mov al,es:[bx+si]
mov ds:[si],al
inc si
loop s_year
inc di
mov ax,di
mov dh,al ;行号
mov dl,12 ;列号
mov cl,2
mov si,0
call show_str
pop cx
add bx,10H
loop year
;************************************************
;************************************************
mov di,1
mov bx,0
mov si,0
mov cx,21
sumn:
push cx
mov ax,es:[bx+5]
mov dx,es:[bx+7]
call dwtoc
inc di
mov ax,di
mov dh,al
mov dl,23
mov cl,0ah
mov si,0
call show_str
pop cx
add bx,10H
loop sumn
;************************************************
;************************************************
mov di,1
mov bx,0
mov si,0
mov cx,21
ne:
push cx
mov ax,es:[bx+0aH]
mov dx,0
call dwtoc
inc di
mov ax,di
mov dh,al
mov dl,35
mov cl,0ch
mov si,0
call show_str
pop cx
add bx,10H
loop ne
;************************************************
;************************************************
mov di,1
mov bx,0
mov si,0
mov cx,21
xx: push cx
mov ax,es:[bx+0dH]
mov dx,0
call dwtoc
inc di
mov ax,di
mov dh,al
mov dl,45
mov cl,06h
mov si,0
call show_str
pop cx
add bx,10H
loop xx
;************************************************
;************************************************
mov ax,4c00H
int 21H
; ###############################################
; #### ####
; #### 子 程 序 ####
; #### ####
; ###############################################
;###################show_str#####################
;名称:show_str
;功能:在指定位置,用指定颜色,显示一个用0结束的字符串
;参数:(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79)
; (cl)=颜色,ds:si指向字符串首地址
;返回:无
show_str:
push ax
push bx
push cx
push dx
push si
push es
show_str_start:
mov ax,0b800h
mov es,ax
; 计算行偏移 ,结果在ax中
mov al,160
mul dh
; 计算列偏移 ,结果在dx中
mov dh,0
add dx,dx
;计算总偏移,结果放在bx中
mov bx,ax
add bx,dx
;到目前,es:[bx]指向目标显存
mov dl,cl
string_copy:
mov cl,[si]
mov ch,0
jcxz string_copy_ok ;当(ds:[si])==0时跳出循环
mov es:[bx],cl
mov es:[bx+1],dl
inc si
add bx,2
jmp short string_copy
string_copy_ok:
pop es
pop si
pop dx
pop cx
pop bx
pop ax
ret
;####################divdw#######################
;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
;参数:(ax)=dword型数据低16位,(dx)=dword型数据高16位,(cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位,(cx)=余数
;应用举例:计算1000000/10(f4240H/0aH)
divdw:
push bx
push ax
; 被除数高位除CX 27/2 --> AX 商 DX 余数
mov ax,dx
mov dx,0
div cx
mov bx,ax ;商的高16位暂时存放在BX中
; 商在AX中,余数在DX中
; 余数就是最终的余数放到CX中去,商就是最终的商的低16位,不用动!
pop ax
div cx
mov cx,dx
mov dx,bx
pop bx
ret
;###################dtoc#########################
;名称:dwtoc
;功能:将dword型数据转变为表示十进制数的字符串,字符串以0为结尾符。
;参数:(ax)=dword型数据的低16位,(dx)=dword型数据的高16位,ds:si指向字符串的首地址
;返回:无
dwtoc:
mov cx, 0
push cx
s_dwtoc:
mov cx,10; 除数
call divdw; 余数在cx中
add cx,30h
push cx; 保存余数的ASCII形式
; 判断是否商为0,如果高低16位都为0,则返回
mov cx,dx
jcxz ok_dxz;
; 高位不为0,则直接跳回,继续执行运算
jmp short s_dwtoc
; 商的高位为0
ok_dxz:
mov cx,ax
jcxz ok_axz
jmp short s_dwtoc
; 商的低位为0
ok_axz:
; 赋值到 ds:[si]
mov dx, si; 保存si,si为字符串的首地址
loop_dtoc:
pop cx
mov ds:[si], cl
jcxz end_dwtoc
inc si
jmp short loop_dtoc
mov si, dx
end_dwtoc:
mov ax, 0
mov ds:[si], ax
mov si,dx
ret
;#######################################################
codesg ends
end start
运行截图:
代码完善(增加一个延时代码,可以竖的一列一列刷新)
delay:
push cx
mov cx,30h
delay_s1:
push cx
mov cx,0
delay_s2:
loop delay_s2
pop cx
loop delay_s1
pop cx
ret
课上的另外一种实现(增加一个延时代码,可以横的一行一行刷新)
assume cs:code,ss:stack
data segment
; bx= 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'
;以上是表示21年的21个字符串
;bx+84
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 245980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型数据
; bp = 168
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
table segment
db 21 dup ('year x y z ',0)
; 0 ;8 ;19 ;28
table ends
stack segment
db 64 dup(0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,64
mov ax,data
mov es,ax
mov bx,0
mov bp,168
mov ax,table
mov ds,ax
mov si,0
mov cx,21
pidea_21:
;复制年份
mov ax,es:[bx]
mov [si],ax
mov ax,es:[bx+2]
mov [si+2],ax
;将总收入转换为字符串后,复制到table段中 ds:(si+8)
mov ax,es:[bx+84]
mov dx,es:[bx+84+2]
push si
add si,8
call dtoc
pop si
;将雇员人数转换为字符串后,复制到table段中 ds:(si+19)
mov ax,es:[bp]
mov dx,0
push si
add si,19
call dtoc
pop si
;计算平均收入后转换为字符串,再复制到table段中 ds:(si+28)
mov ax,es:[bx+84]
mov dx,es:[bx+84+2]
div word ptr es:[bp]
; ax 存放的就是平均收入
mov dx,0
push si
add si,28
call dtoc
pop si
;计算行号的问题?
; si/32
mov ax,si
push bx
push cx
mov bl,32
div bl
mov dh,al ;行号进dh
mov dl,0
mov cl,2h
call show_str
pop cx
pop bx
call delay
add bx,4
add bp,2
add si,32
loop pidea_21
mov ax,4c00h
int 21h
; 延时子程序delay
delay:
push cx
mov cx,30h
delay_s1:
push cx
mov cx,0
delay_s2:
loop delay_s2
pop cx
loop delay_s1
pop cx
ret
; 显示字符串子程序show_str
; 参数1 ds:si指向要显示的字符串首地址,字符串以0结尾
; 参数2 行号dh(0~24)
; 参数3 列号dl(0~79)
; 参数4 颜色属性 cl
show_str:
push ax
push bx
push cx
push dx
push si
push es
show_str_start:
mov ax,0b800h
mov es,ax
; 计算行偏移 ,结果在ax中
mov al,160
mul dh
; 计算列偏移 ,结果在DX中
mov dh,0
add dx,dx
;计算总偏移,结果放在BX中
mov bx,ax
add bx,dx
;到目前,es:[bx]指向目标显存
mov dl,cl
string_copy:
mov cl,[si]
mov ch,0
jcxz string_copy_ok
mov es:[bx],cl
mov es:[bx+1],dl
inc si
add bx,2
jmp short string_copy
string_copy_ok:
pop es
pop si
pop dx
pop cx
pop bx
pop ax
ret
; 解决除法溢出的子程序divdw
; 参数1 被除数 dx+ax 32位组合
; 参数2 除数 cx
; 返回值 商:dx+ax 余数: cx
divdw:
push bx
push ax
; 被除数高位除CX 27/2 --> AX 商 DX 余数
mov ax,dx
mov dx,0
div cx
mov bx,ax ;商的高16位暂时存放在BX中
; 商在AX中,余数在DX中
; 余数就是最终的余数放到CX中去,商就是最终的商的低16位,不用动!
pop ax
div cx
mov cx,dx
mov dx,bx
pop bx
ret
; 改进后的dtoc 子程序,支持转换dword型数据
; 参数1 ds:si 指向最终字符串首地址
; 参数2 待转换的dword型数据 dx(高位)+ax(低位)
dtoc:
push ax
push bx
push cx
push dx
push si
push di
dtoc_start:
mov di,0 ; 用di 存放压入的数据个数
pick:
mov cx,10 ;divdw子程序中的除数,被除数不用动
call divdw
add cx,30h
push cx
inc di
mov cx,dx
jcxz next
jmp short pick
next:
mov cx,ax
jcxz pick_ok
jmp short pick
pick_ok:
mov cx,di ; 确定弹出的数据个数
; 堆栈中的数据出栈,送到目标内存位置
dtoc_move:
pop ax
mov ds:[si],al
inc si
loop dtoc_move
; 在字符串末尾添加一个结束符0
;mov byte ptr [si],0
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start
截图