. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  设计一终于ok了.2天多时间...哭了.  [待解决] 回复[ 1次 ]   点击[ 493次 ]  
kingwrcy
[帖 主]   [ 发表时间:2009-04-15 19:05 ]   [引用]   [回复]   [ top ] 
荣誉值: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
mess
[第1楼]   [ 回复时间:2009-04-17 15:07 ]   [引用]   [回复]   [ top ] 
荣誉值:337
信誉值:0
注册日期:2008-01-01 17:48
雨过见彩虹,恭喜楼主啊~
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved