汇编网首页登录博客注册
mqmelon的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
最新留言
好友圈
友情链接

[2012-12-06 10:04] 第10章 实验2 完整程序

写汇编程序真不容易,调试起来更是困难。光t就不知按了多少。总算完成了。
;主程序
DATAs segment
        ;以下来年份数据
                db '1975','1976','1977','1978','1979'
                db '1980','1981','1982','1983','1984'
                db '1985','1986','1987','1988','1989'
                db '1990','1991','1992','1993','1994'
                db '1995'
                ;以下为收入数据
                dd 16,22,382,1356,2390
                dd 8000,16000,24486,50065,97479
                dd 140417,197514,345980,590827,803530
                dd 1183000,1843000,2759000,3753000,4649000
                dd 5937000
                ;以下为人员数据
                dw 3,7,9,13,28
                dw 38,130,220,476,778
                dw 1001,1442,2258,2793,4037
                dw 5635,8226,11542,14430,15257
                dw 17800
DATAS ends

        ;结果存储段
        table segment
                db 21 dup('                           ') ;每行27个字节,共21行
        table ends

STACKS SEGMENT 
    ;此处输入堆栈段代码 
    dw 16 dup (0) 
STACKS ENDS

CODES segment

         ASSUME CS:CODES,DS:DATAS,SS:STACKS 

start:
        MOV AX,DATAS 
    MOV DS,AX 
     
    mov ax,STACKS 
    mov ss,ax 
        
        mov ax,table
        mov es,ax ;将存储表格置es段
     
    ;此处输入代码段代码 
        ;计算平均数
        mov si,0 ;数据段偏移
        mov di,0 ;数据段偏移
        mov bx,0 ;计算行数
        ;循环
        ;mov cx,2 ;测试,先用两行,便于调试
        mov cx,15h ;共21行
        calavg: ;
        ;循环
        ;取各种数据
        mov ax,[si] ;年
        mov es:[bx],ax
        mov ax,[si+2]
        mov es:[bx+2],ax
        mov es:[bx+4],20h ;空格
        ;收入        
        mov ax,[si+54h] ;低位 //收入
        mov dx,[si+54h+2h] ;高位 //收入
        push ds
        push si
        push bx
        mov bx,es
        mov ds,bx
        pop bx
        ;add bx,5 ;
        mov si,bx ;收入在表格中位置
        add si,5 ;收入偏移
        call ddtoc ;收入转
        pop si
        pop ds
        mov es:[bx+0ch],20h ;空格
        ;人数
        mov ax,[di+0a8h];
        ;
        push ds
        push si
        push bx
        mov bx,es
        mov ds,bx
        pop bx
        mov si,bx ;+13
        add si,0dh ;人数偏移
        call dtoc ;人数转
        pop si
        pop ds
        mov es:[bx+12h],20h ;空格
        
        ;求平均值
        push cx ;用
        ;
        mov ax,[si+54h]
        mov dx,[si+54h+2]
        mov cx,[di+0a8h] ;除数 //人数
        call divdw ;计算平均数
        push ds
        push si
        push bx
        mov bx,es
        mov ds,bx
        ;mov si,[bx+19]
        pop bx
        mov si,bx
        add si,13h ;平均值偏移
        call ddtoc ;平均数值转换
        pop si
        pop ds
        mov es:[bx+1ah],0 ;停止符号,注意,此处写入一个word类型的0,不符合要求,应该写入一个byte类型
        
        pop cx ;
        
        ;计算步长
        add bx,27 ;行步进
        add si,4 ;年份及收入步进
        add di,2 ;人数步进
        
        loop calavg ;
        
        ;
        ;以下为显示部分
showcom:
        ;mov cx,15h ;共21行数据
        push ds
        push bx
        push es
        push dx
        push si
        push ax
        push cx
        ;showOneLine:
        ;
;        push cx
        ;mov ax,15h ;共21行数据
        ;mov ax,2h ;先调试两行
        ;mov cx,2h ;调试2行
        mov cx,15h ;共21行数据
        ;
        mov bx,es
        mov ds,bx ;ds:指向es段地址
        mov bx,0
        ;
        mov dh,1h ;第一行
        ;
        showOneLine:
        mov ax,cx ;保存循环变量
        mov cl,2h ;绿字,黑底
        mov dl,1h ;第一列
        mov si,bx ;指向第一个字符
        call show_str ;显示
        
        add bx,1bh ;增27字节
        inc dh ;行自增
        inc dh ;行自增,在显示中,dh会被减1
        ;dec ax ;ax自减
        mov cx,ax ;判断是否退出
        ;pop cx
        
        loop showOneLine ;
        ;
        pop cx
        pop ax
        pop si
        pop dx
        pop es
        pop bx
        pop ds
        ;返回到dos
        mov ax,4c00h
        int 21h

;显示字串子程序
;显示字符串到指定位置
;函数名称:show_str
;函数功能:在指定位置用指定颜色显示一个用0结束的字符串
;函数参数:(dh)=行号0-24,(dl)=列号0-79,(cl)=颜色,ds:si为字串首地址
show_str:
        ;入栈 
    push es 
    push ax 
    push bx 
    push di 
    push cx 
    ;显存地址 
    mov ax,0B800H 
    mov es,ax 
    mov di,0 ;行列偏移地址 
    ; 
    mov ax,0a0h ;行偏量 
    dec dh ;行减1 
    mul dh ;计算行偏移 
    mov di,ax ;将行偏移保存在di中 
    ; 
    mov ax,2h 
    dec dl ;列减1 
    mul dl ;计算列偏移 
     
    add ax,di 
    mov di,ax 
    ; 
    mov bh,cl ;属性 
    ; 
    showOne: 
    mov bl,ds:[si] ;取一个字母 
    mov cl,bl ;判断是否为0 
    mov ch,0 
    jcxz OK 
     
    ;mov es:[di+ax],bx ;显示到屏幕上 
    mov es:[di],bx 
    inc si ;到下一个字母位置 
    add di,2 ;列移2个位置到下一列 
    jmp showOne ;循环 
     
    OK: 
    ;出栈 
    pop cx 
    pop di 
    pop bx 
    pop ax 
    pop es 
    ;返回 
    ret ;显示字串子程序show_str结束 

;显示子程序结束
        ;
;非溢出除法
;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
;该公式的意思表示为:高16位除以除数时,得到其商和余数,其中的余数正好是下一次16位除法时的高16位。
;16位除法DX中为被除数高位(H);AX中为被除数低位(L);其结果中AX中为商,DX中为余数;
;参数:(ax)-被除数低位 (dx)-被除数高位 (cx)-除数
;返回值:(dx)商中高位,(ax)商中低位,(cx)余数
divdw:
        ;保存现场
        push bx
        ;开始第一次除法
        push ax ;保存被除数中的低16位,该数据在ax中
        mov ax,dx ;将被除数中的高16位放在ax中,然后将dx置0,此时(dx)(=0)+(ax)即为第一次除法的被除数
        mov dx,0 ;第一次除法时的被除数,高位置0
        div cx ;第一次除法时的除数
        ;第一次除法结束时,ax中为商,即dx中余数,此时的余数就是第二次除法中的高16位
        mov bx,ax ;保存第一次除法时的商,即总结果中的高16位商
        pop ax ;总被除数中低16位出场
        div cx ;第二次除法
        mov cx,dx ;第二次除法中的余数,即总结果中的余数
        mov dx,bx ;第一次结果中保存的商中的高16位
        
        divExit: ;子程序退出
        pop bx
        ret ;divdw子程序结束
;非溢出除法子程序结束
        
;十进制转换字符串函数
;子程序名称:dtoc
;功能:将word型数据转变为十进制了字符串,以0为结束符
;参数:(ax)=Word型数据,ds:si字符串的首地址
;返回:无(void)
dtoc:
        ;保存现场
        ;入栈
        push dx
        push bx
        push cx
        push di
        push si
        ;
        mov di,0 ;计数器置0,用来计算余数的个数
        mov bx,0ah ;除数10(0aH)
        mov cx,0 ;清空
        ;
divone: ;除0ah,取余数
        mov dx,0
        div bx
        mov cx,dx ;此时dx中为余数
        push cx ;将余数入栈
        inc di ;计数器自增
        mov cx,ax ;此处将商赋值给 cx,以判断是否结束转换        
        jcxz divover ;跳至取余结束
        ;不能结束
        jmp divone ;跳到取余动作
        ;
divover: ;取余结束
        mov cx,di ;将余数的数量送入cx,以循环
stackOne:
        ;将保存的余数出栈
        pop ax
        add ax,30h ;将得到的数加30(1e)
        mov [si],al ;将得到的数保存到指定内存地址
        inc si ;内存地址自增1
        loop stackOne
        ;将结束符号写入
        ;inc si
        ;mov [si],0
        
        ;出栈
        pop si
        pop di
        pop cx
        pop bx
        pop dx
        ret ;dtoc子程序结束,返回调用
        
;十进制转换字符串子程序结束

;十进制转换字符串函数
;子程序名称:ddtoc
;功能:将double word型数据转变为十进制了字符串,以0为结束符
;参数:(ax)=Word型数据的低16位,(dx)double word数据高16位,ds:si字符串的首地址
;返回:无(void)
ddtoc:
        ;保存现场
        ;入栈
        push dx
        push bx
        push cx
        push di
        push si
        ;
        mov di,0 ;计数器置0,用来计算余数的个数        
        ;
ddivone: ;除0ah,取余数
        mov cx,0ah ;除数
        call divdw ;用非溢出除法子程序
        ;返回后商的高位在dx中,低位在ax中,而余数在cx中
        push cx ;将余数入栈
        inc di ;计数器自增
        mov cx,ax ;将商放入cx中,以判断是否结束转换
        jcxz ddivover ;跳至取余结束
        ;得新取被除数
        
        jmp ddivone ;跳到取余动作
        ;
ddivover: ;取余结束
        mov cx,di ;将余数的数量送入cx,以循环
dstackOne:
        ;将保存的余数出栈
        pop ax
        add ax,30h ;将得到的数加30(1e)
        mov [si],al ;将得到的数保存到指定内存地址
        inc si ;内存地址自增1
        loop dstackOne
        ;将结束符号写入
        ;inc si
        ;mov [si],0
        
        ;出栈
        pop si
        pop di
        pop cx
        pop bx
        pop dx
        ret ;dtoc子程序结束,返回调用
        
;十进制转换字符串子程序结束
        
CODES ends
end start
评论次数(0)  |  浏览次数(596)  |  类型(汇编作业) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码