荣誉值:0
信誉值:2
注册日期:2007-12-10 17:12 |
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
stack segment
dd 32 dup (0)
stack ends
tmp_data segment
dw 200 dup (0)
tmp_data ends
code segment
start:
mov dh,5
mov cx,2
mov dl,16
wel segment
db 'Power Idea Company Fundamental State From 1975 To 1995',0;55个字节
db 9 dup (0)
db '===============================================================================',0
db 'Year Income Employee Avg ',0
wel ends
mov ax,wel ;头信息输出
mov ds,ax
call show_str
mov ax,ds
add ax,4
mov ds,ax
inc dh
mov dl,0
call show_str
mov ax,ds
add ax,5
mov ds,ax
inc dh
mov dl,16
call show_str
mov cx,21
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,128
call copy_to ;3组数据按要求copy到es段.
mov ax,es
mov ds,ax ;ds指向新的数据区
mov bx,0
inc dh
flag:
mov dl,16 ;从第16列开始
push cx ;保存计数器
mov cx,2 ;样式为2,绿色
call show_str;显示年份
push dx ;保存行列参数
mov ax,ds:[5];收入前2位
mov dx,ds:[7];收入后2位
call dwtoc ;转化收入位ascii码
pop dx ;恢复行列参数
add dl,16 ;空开16列
call show_str;显示收入
mov ax,ds:[10]
call dtoc ;转化员工
add dl,16 ;空开16列
call show_str;显示员工
mov ax,ds:[13]
call dtoc ;转化员工
add dl,16 ;空开16列
call show_str;显示员工
inc dh ;行数+1
pop cx ;计数器出栈
mov dl,16 ;从16列开始
mov ax,ds ;ds段像下移动16个字节.到下一年的数据.
add ax,1
mov ds,ax
loop flag
mov ax,4c00h
int 21h
dtoc:
;===============================================================================
;功能:将word型数据变为10进制字符串.字符串以0结尾
;参数:ax=word型数据,ds:si指向字符串首地址
;返回值:无
;===============================================================================
push cx ;保存cx
push dx ;保存dx
push bx
mov bx,0
mov cx,0
mov di,0 ;计数器.计算字符串的长度
;mov ax,ds:[si]
s3:
mov cx,ax ;把商送cx,判断是否为0,为0则已除完.
jcxz done ;除完了.跳到逆序的地方
mov dx,0 ;高16位置0
mov cx,10 ;除10
div cx ;ax即为商,dx为余数
add dx,30H ;余数+30H,就是相应的ascii码
push dx ;由于得出的结果是反序.所以要逆序存到ds段去.又因为是字节单位的.所以不能用栈简单的逆序.
inc di ;di自增1,计数器
jmp short s3
done:
mov cx,di ;把计数器内容送cx
s4:pop ax ;余数出栈.
mov [bx],BYTE PTR al ;每次取低位送到ds中对应的位置去.
inc bx
loop s4
mov [di],0 ;最后一位送0,以0结尾
pop bx
pop dx
pop cx
mov si,0 ;使ds:si 指向输出的字符串
;call show_str
ret
dwtoc:
;===============================================================================
;功能:将dword型数据变为10进制字符串.字符串以0结尾
;参数:ax=dword型数据低16位,dx=dowrd型数据的高16位.
;返回值:无
;===============================================================================
push bx
push dx
push cx ;保存cx
mov bx,0
mov cx,0
mov di,0 ;计数器.计算字符串的长度
s1:
mov cx,0AH ;除10
call div_dw
add cx,30H ;余数+30H,就是相应的ascii码
push cx ;由于得出的结果是反序.所以要逆序存到ds段去.又因为是字节单位的.所以不能用栈简单的逆序.
mov cx,ax ;低位商送cx
inc di ;di自增1,计数器
jcxz ok_s ;判断低位商是否是0
jmp short s1
ok_s:
mov cx,dx ;再送高位商
jcxz ok_f ;再判断高位商是否为0
jmp short s1;不为0则继续除以10
ok_f:
mov cx,di ;除完了.把计数器内容送cx
s2:pop ax ;余数出栈.
mov [bx],BYTE PTR al ;每次取低位送到ds中对应的位置去.
inc bx
loop s2
mov [di],0 ;最后一位送0,以0结尾
mov si,0 ;使ds:si指向转化后的字符串
pop cx
pop dx
pop bx
ret
copy_to:
;===============================================================================
;功能:把data段中的3组数据按要求copy到tmp_data段的前400个字节.
;参数:无
;返回值:无
;===============================================================================
push dx
push bx
push si
push di
push cx
mov bx,0
mov si,0
mov di,0
mov cx,21
mov ax,tmp_data
mov es,ax
s0:push [bx+0] ;年份前2位入栈
push [bx+2] ;年份后2位入栈
push [bx+84] ;收入前2位入栈
push [bx+86] ;收入后2位入栈
push [di+168] ;员工入栈
pop es:[si+10] ;员工出栈
pop es:[si+7] ;收入后2位出栈
pop es:[si+5] ;收入前2位出栈
pop es:[si+2] ;年份后2位出栈
pop es:[si+0] ;年份前2位出栈
mov BYTE ptr es:[si+4],0 ;置0
mov BYTE ptr es:[si+9],0
mov BYTE ptr es:[si+12],0
mov BYTE ptr es:[si+15],0
mov ax,es:[si+5] ;收入的低2位
mov dx,es:[si+7] ;收入的高2位
push cx ;保存cx计数器以便于除法
mov cx,es:[si+10]
call div_dw
mov es:[si+13],ax ;平均值
pop cx ;恢复cx计数器
add bx,4
add si,16
add di,2
loop s0
pop cx
pop di
pop si
pop bx
pop dx
ret
show_str:
;===============================================================================
;功能:显示ds段开始的字符串在dh行。dl列。样式为cl,字符串以0结尾
;参数:ds段
;返回值:无
;===============================================================================
push dx
push cx
push bx
push es
mov al,0A0H ;一行160个字节
dec dh ;行数从0开始.所以dh-1
mul dh ;一共160*(dh-1)个字节
mov bx,ax ;送bx
mov al,2 ;一列2个字节
mul dl ;一共2*dl个字节
push cx
mov cx,ax
jcxz index ;如果从0列开始则不减2
sub ax,2 ;列也是从0开始.并且字符放奇数位.所以ax-2
index:add bx,ax ;行列相加
mov ax,0B800H ;基址为0B800H
mov es,ax ;送es
mov si,0
mov ch,0 ;高位置0
mov di,0
pop cx
mov ax,cx ;保存样式到ax
s:
mov cl,[di] ;送cx
jcxz ok ;判断是否到字符串尾,是则返回.否则继续
mov es:[bx+si],cl ;奇数位,字符串
mov es:[bx+si+1],al ;偶数位,样式
inc di
add si,2
jmp short s
ok:
pop es
pop bx
pop cx
pop dx
ret
div_dw:
;===============================================================================
;功能:进行不会产生溢出的除法运算.被除数为dword型.除数为word型.结果为dword型
;参数:ax dword型的低16位.dx dword型的高16位,cx为除数
;返回值:dx为商的高16位.ax为商的低16位,cx为余数
;===============================================================================
push bx
push ax ;保存低16位进栈
mov ax,dx ;把高16位放进ax
mov dx,0 ;把dx置0,所以dx:ax = 0:ax
div cx ;就是0:ax/cx,就是公式中的int(H/N),dx是余数
mov bx,ax ;把求得的商保存在bx
pop ax ;恢复低16位到ax
div cx ;就是dx:ax/cx,也就是第一次的余数*10000H+低16位/cx,商在ax,余数在dx中
mov cx,dx ;按题目要求把余数送到cx中
mov dx,bx ;把第一求得高16位的商放进dx中.低16位的商默认在ax中.
pop bx
ret ;return
code ends
end start
最后的运行结果:
ps:貌似没显示完.应该到1995年.屏幕小了.
就是4个函数的调用.一个显示字符串.2个转换数字到ascii码的函数.一个转word型.一个转dword型的.还有个函数就是按要求copy数据的函数...花了我2天时间.
D:\vcstart\asm>exp10.exe
D:\vcstart\asm>
Power Idea Company Fundamental State From 1975 To 1995
===============================================================================
Year Income Employee Avg
1975 16 3 5
1976 22 7 3
1977 382 9 42
1978 1356 13 104
1979 2390 28 85
1980 8000 38 210
1981 16000 130 123
1982 24486 220 111
1983 50065 476 105
1984 97479 778 125
1985 140417 1001 140
1986 197514 1442 136
1987 345980 2258 153
1988 590827 2793 211
1989 803530 4037 199
1990 1183000 5635 209
1991 1843000 8226 224
1992 2759000 11542 239 | | |