鱼C论坛

 找回密码
 立即注册
查看: 2413|回复: 4

[汇编作业] 课程设计1

[复制链接]
发表于 2017-12-7 13:15:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 kingfon 于 2017-12-7 13:16 编辑

ks1.PNG

;思路:将原始数据通过字符转换程序写入table表中,再通过显示子程序将table表中的数据写入显存
;table表内存空间计算,每行字节数,年份5个字节(包含0),收入8个字节(包含0)
;员工数6个字节(包含0),平均收入6个字节(包含0),合计25字节,共21行

assume cs:code, ds:data
data segment
        db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984'
        db '1985','1986','1987','1988','1989','1990','1991','1992','1993','1994'
        db '1995'
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980
        dd 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,11542,14430,15257,17800
data ends

table segment
        db 525 dup (0)                        ;25*21=525字节
table ends

stack segment
        dw 30 dup (0)
stack ends

code segment
start:
        mov ax,data
        mov ds,ax
        mov ax,stack
        mov ss,ax
        mov sp,60
        mov ax,table
        mov es,ax
        mov bx,0                                ;原始数据年份起始偏移地址,每个数据相差4个字节,总收入也是相差4个字节
        mov si,0                                ;原始数据员工数起始偏移地址,每个数据相差2个字节
        mov di,0                                ;table表中起始位置偏移地址
        mov cx,21
        put:                                        ;将数据处理放入table表
                mov ax,[bx]
                mov dx,[bx+2]
                mov es:[di],ax
                mov es:[di+2],dx                ;将年份写入table表中对应位置
                mov ax,[bx+84]                        ;将收入(4个字节)通过子程序处理成阿拉伯数字再存入目标位置,取低16位存入ax
                mov dx,[bx+86]                        ;取高16位存入dx
                push di                                        ;di参与主程序的循环,接下来要做为table表的偏移地址传给子程序,要暂存起来
                add di,5                                ;将写入table表中的起始位置给子程序
                call dtoc                                ;调用子程序
                pop di                                        ;调用结束还原di的值
                mov ax,[si+168]                        ;将员工数(2个字节)通过子程序处理成阿拉伯数字再存入目标位置,同上
                mov dx,0                                ;原始数据为16位,dx置0
                push di
                add di,13
                call dtoc
                pop di
                mov ax,[bx+84]                ;计算平均收入(2个字节)并通过子程序处理成阿拉伯数字再存入目标位置
                mov dx,[bx+86]
                push cx                                ;将要调用的子程序需用cx作为除数做为参数,返回的cx值是余数,先将循环次数暂存
                mov cx,[si+168]
                call divdw                        ;调用除法子程序得出商低16放ax,高16位放dx
                push di
                add di,19                        ;指定平均收入数据在table表中的偏移地址
                call dtoc                        ;将平均收入数据写入table表中
                pop di
                pop cx                                ;从栈中取回循环次数
                add di,25                        ;定位table表中下一条记录起始位置,每条记录长度25字节
                add bx,4                        ;改变下次循环年份的起始位置,每次递增4个字节
                add si,2                        ;改变下次循环员工数的起始位置,每次递增2个字节
                loop put
                mov ax,table                ;输出显示器的程序,table表作为原始数据
                mov ds,ax
                mov si,0                        ;从table表中第0个字节开始读取
                mov cx,21                        ;输出21行
                mov dh,3                        ;从第3行开始
                mov al,7                        ;定义颜色,黑底白字
               
        display:                                ;将数据输出到显示器
                mov dl,15                        ;每行从第15列开始
                call show_str                ;输出年份
                add dl,13                        ;列与列间距
               
                push si                                ;si将作为参数传给子程序,暂存       
                add si,5                        ;定位table表中总收入起始位置偏移地址
                call show_str                ;输出总收入
               
                add dl,13
                add si,8                        ;定位table表中员工数起始位置偏移地址
                call show_str                ;输出员工数
                add dl,13
               
                add si,6                        ;定位table表中平均收入起始位置偏移地址
                call show_str                ;输出平均收入
               
                inc dh                                ;换行
                pop si                                ;一行输出结束,还原si值
                add si,25                        ;取table表下一条记录起始偏移地址
                loop display
       
        mov ax, 4c00h
    int 21h

show_str:                        ;dh存放行数1-25,dl存放列数1-80,al存放颜色值,si存放原始数据位置偏移地址
        push cx                        ;子程序用到的寄存器值暂时入栈
        push si
        push dx
        push ax
        push bx
        mov bh,al                ;将颜色值存入bh
        push ax                        ;接下来要更换显存的段地址,要用到ax,先暂存ax值
        mov ax,0b800h        ;将显存段地址给es
        mov es,ax
        pop ax                        ;之前存了颜色值,出栈
        dec dh                        ;计算机用0做为起始地址,此处dh-1
        dec dl                        ;同上
        mov al,160                ;计算目标行数、列数的起始偏移地址,每行160个字节,颜色80个字节,要显示的字符80个字节
        mul dh                        ;行数*160,得到行数
        mov di,ax                ;将行的位置存入di
        mov al,2                ;计算列的起始位置,每个字符2个字节
        mul        dl                        ;列数*2
        add di,ax                ;把结果与di相加,最终定位目标偏移地址
        write:
                mov ch,0
                mov cl,[si]                        ;将原始字符的ascii值给cx,遇0写入结束
                jcxz ok
                mov bl,[si]                        ;将字符放在bl中,bh此时存放颜色
                mov es:[di],bx                ;写入显存
                inc si                                ;原始数据偏移地址+1
                add di,2                        ;显存偏移地址+2
                jmp short write
        ok:
                pop bx                ;子程序运行前的寄存器值依次出栈
                pop ax
                pop dx
                pop si
                pop cx
                ret
               
dtoc:                        ;将给定的数字以阿拉伯数字的形式存放在内存中,参数ax存放原数据的低16位,dx存放原数据的高16位,di为目标位置偏移地址的开始位置
        push cx
        push bx
        push di
        mov bx,0                        ;用于存放取余的次数
        chu:
                mov cx,10                        ;除数10,取余
                call divdw                        ;为避免运算过程中出现除法溢出,除法运算调用处理过除法溢出的子程序
                push cx                                ;将余数进栈
                push ax                                ;先将ax暂存
                or ax,dx                        ;因子程序返回的商为32位,为证明商是否为0,不能单纯判断低16位的值是否为0,dx中高16位的数也要做为判断依剧
                mov cx,ax                        ;上步运算结果若为0,表示得到的商为0,取余过程结束
                pop ax                                ;若执行or ax,dx之后,ax中的值不为0就要继续取余,所以还原ax的值
                inc bx                                ;取余次数加1
                jcxz s2                                ;取到商为0时,跳到s2
                jmp short chu                ;商不为0继续取余
        s2:
                mov cx,bx                        ;将取余的次数作为写入数字的次数,原数几位数就写几次
        s3:
                pop ax                                ;将前面取余的数出栈
                add al,30h                        ;除数是10,余数为0-9
                mov es:[di],al                ;存入di位置,单个字节
                inc di                                ;指向下一个地址
                loop s3
                pop di
                pop bx
                pop cx
                ret
divdw:                        ;被除数ax存放低16位,dx存放高16位,cx存放除数,运算结束ax存放商,dx存放余数
        push bx                        ;因这个子程序要用到bx,所以开始前先将其暂存,以免修改了调用者的数值
        push ax                        ;低16位暂存
        mov ax,dx                ;高16位移到ax,即右移16位
        mov dx,0                ;dx置0,确保以下的除法不会溢出
        div cx                        ;16位除法,结果ax为商,dx为余数
        mov bx,ax                ;将商暂存在dx中
        pop ax                        ;原低16位放回ax中,此时dx中的数是余数,小于除数,所以再进行1次16位除法也不会溢出
        div cx                       
        mov cx,dx                ;第二次除法后就有结果了,将余数给cx返回给调用者
        mov dx,bx                ;第一次的除法实际是右位16位再除,得到的商最后还是放回高16位
        pop bx
        ret

code ends

end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-12-18 16:27:54 | 显示全部楼层
不是很能看得懂add di,5 add di,13 add di,19 add di,25这几句,能给我讲讲吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-12-20 09:32:00 | 显示全部楼层
90182si 发表于 2017-12-18 16:27
不是很能看得懂add di,5 add di,13 add di,19 add di,25这几句,能给我讲讲吗

思路:将原始数据通过字符转换程序写入table表中,再通过显示子程序将table表中的数据写入显存
table表内存空间计算,每行字节数,年份5个字节(包含0),收入8个字节(包含0)
员工数6个字节(包含0),平均收入6个字节(包含0),合计25字节,共21行
我们把每一年的年份、总收入、员工数、平均收入当作是一条记录存入table表中,那每条记录上面根据分析就
要占用25个字节,年份的每行的偏移地址是di,总收入是di+5,员工数是di+13,平均收入是di+19,1条记录处理结束后,下一条记录开始di+25,依此类推
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-20 12:26:02 | 显示全部楼层
kingfon 发表于 2017-12-20 09:32
思路:将原始数据通过字符转换程序写入table表中,再通过显示子程序将table表中的数据写入显存
table表 ...

谢谢,我写出来了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-20 12:26:40 | 显示全部楼层
kingfon 发表于 2017-12-20 09:32
思路:将原始数据通过字符转换程序写入table表中,再通过显示子程序将table表中的数据写入显存
table表 ...

谢谢,我写出来了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 17:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表