汇编课程设计:汇编语言课程设计1

在辅导学长的带领下,三个一工程的第一大阶段已经结束,对于这段时间所学的汇编知识做一个总结,我将几个难点实验和综合研究写成博客既是总结,也方便学习汇编语言的你们拿去参考。

课程设计一:

1.分析:

1)在实验七中,已经实现了将这些数据写入到了table段内存中;现在我们要的就是将table段内存读取出来后,有的数据不是字符串,需要将数字转换成字符串形式;写入显存。直接将实验七的程序改造成一个子程序,在主程序中直接调用。

2)table段数据的读取并写入一个临时的内存存储段—data段:对于字符串(例如:年份),我们直接写入目标内存,并加入0标记;对于其他的数值,我们调用实验10中的dtoc子程序,转换成字符串后写入目标内存段。此时在data段中存储的都是字符串形式的,并且以0为结尾。此处,得用新的32位转换子程序ddtoc。在ddtoc子程序中,会用到除法,而由于对应 “收入”的数据,采用的是dd类型,在dtoc子程序中,除法指令div运算的结果ax已经放不下,调用divdw子程序来实现。

3)程序的大体框架是:将实验七的程序作为一个子程序—to_table;主程序调用to_table子程序将表格数据写入内存,然后再将表格型数据从内存中取出放入data段,读取的数值需调用ddtoc将数字转换成字符串,转换时又会调用divdw子程序,读取的字符串就直接放入,最后调用show_str来显示字符串。

2.程序:

assume cs:code data1 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 45980,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,17800data1 ends table segment db 21 dup ('year summ ne ?? ') table endsdata segment db 10 dup (0)data endscode segmentstart: mov ax,data1 mov ds,ax mov ax,table mov es,ax call to_table ;调用子程序 call cls ;清屏子程序 mov ax, table mov es, ax mov bx, 0 mov ax, data mov ds, ax mov si, 0 mov cx, 21 mov dh, 1 ;show_str的入口参数。show_info: push cx ;显示年份 mov ax, es:[bx] mov ds:[si], ax mov ax, es:[bx+2] mov ds:[si+2], ax mov byte ptr ds:[si+4], 0 ;以0作为字符串结尾。 mov dl, 3 ;设置入口参数:所在行的列数,从第几列开始显示 mov ch, 0 ;ch清零,防止高8位不为零。 mov cl, 2 call show_str ;显示总收入 push dx ;后面要使用dx变量,先保存dx mov ax, es:[bx+5] ;将总收入的低16位送入ax mov dx, es:[bx+7] ;将总收入的高16位送入dx,ddtoc的入口参数 call ddtoc pop dx ;恢复寄存器dx,此时dh也就恢复了。 mov dl, 14 ;所在行的列数 mov ch, 0 ;ch清零,防止高8位不为零。 mov cl, 2 call show_str ;显示公司总人数 push dx mov ax, es:[bx+10] mov dx, 0 call ddtoc pop dx mov dl, 34 ;所在行的列数 mov ch, 0 ;ch清零,防止高8位不为零。 mov cl, 2 call show_str ;显示人均收入 push dx mov ax, es:[bx+13] mov dx, 0 call ddtoc pop dx mov dl, 50 ;所在行的列数 mov ch, 0 ;ch清零,防止高8位不为零。 mov cl, 2 call show_str add bx, 10H ;bx指向下一行。(table中16字节是一行) mov si, 0 add dh, 1 ;累加dh(下一行显示) pop cx ;弹栈到cx,计数器自动减1. loop show_info ;循环,直到cx=0 mov ax, 4c00H int 21H to_table: ;保护寄存器变量 push ax push ds push es push bx push si push di push cx mov bx,0 mov si,0 mov di,0 mov cx,21 ;初始化计数器 s66: ;写入年份 mov ax,0[bx] mov es:0[si],ax mov ax,2[bx] mov es:2[si],ax ;写入空格 mov al,20H mov es:4[si],al ;写入收入 mov ax,84[bx] mov es:5[si],ax mov ax,86[bx] mov es:7[si],ax ;写入空格 mov al,20H mov es:9[si],al ;雇员数 mov ax,168[di] mov es:10[si],ax ;写入空格 mov al,20H mov es:12[si],al ;除法后写入人均收入 mov ax,[bx+84] mov dx,[bx+86] ;没有办法,用个bp变量吧 mov bp,[di+168] div bp mov es:13[si],ax ;写入空格 mov al,20H mov es:15[si],al ;bx、si、di变量的递增 add bx,4 add si,16 add di,2 loop s66 ;恢复寄存器变量,并返回主调程序 pop cx pop di pop si pop bx pop es pop ds pop ax ret ddtoc: push ax push cx push bx push si push bp push dx mov si, 0 change: mov cx, 10 ;设置除数cx=10 mov bx, 0 ;divdw中导致bx变化,故清零 mov bp, 0 ;余数bp=0 call divdw ;将(dx+ax)/cx求余数bp push ax ;将ax和dx压栈保护 push dx add ax, dx ;(dx)+(ax)整个的商的值 mov cx, ax ;将商赋值给cx,判断整个的商是否为0? pop dx ;将ax和dx弹栈恢复 pop ax jcxz last add bp, 30H push bp inc si jmp short change last: ;最后一次也要转换并压栈 add bp, 30H push bp inc si ;将栈中数据倒序写入内存data段中 mov cx, si mov si, 0 write: pop ds:[si] inc si loop write mov byte ptr ds:[si], 0 ;以0作为字符串结尾。 ;恢复寄存器,并返回主调程序。 pop dx pop bp pop si pop bx pop cx pop ax retdivdw: push ax ;将被除数低16位先压栈保存。 mov ax, dx ;(ax)=(dx) mov dx, 0000H ; div cx ;被除数dx+ax(组合),除数cx。 mov bx, ax ;将H/N结果的商先保存在bx中,(bx)=0001H pop ax ;将L值弹栈到ax div cx mov bp, dx ;返回值(cx)等于最终结果的余数 mov dx, bx ;最终结果高16位值=(bx) retcls: push cx push di push si mov ax, 0b800H mov es, ax mov cx, 80*24 ;设置循环次数,屏幕是24行80列 mov di, 0 scr_cls: mov byte ptr es:[di+0], ' ' ;第一个字节写入空格, mov byte ptr es:[di+1], 0 ;第二个字节写入字符属性0(代表黑色无底) inc di inc di loop scr_cls ;恢复寄存器 pop si pop di pop cx retshow_str: push dx push cx push si push bx push es mov ax, 0b800H mov es, ax ;设置显示缓冲区内存段 mov ax, 0 ;(ax)= 0,防止高位不为零 mov al, 160 ;0a0H- 160字节/行 mul dh ;相对于0b800:0000第dh行偏移量 mov bx, ax ;将第(dh)行的偏移地址送入bx,bx代表行偏移 mov ax, 0 mov al, 2 ;列的标准偏移量是2个字节 mul dl ;同一行列的偏移量,尽量使用乘法,(al)=列偏移 add bx, ax ;最终获得偏移地址(bx)=506H mov di,0 mov al, cl mov ch, 0 show: mov cl, ds:[si] jcxz ok mov es:[bx+di+0], cl mov es:[bx+di+1], al add di, 2 inc si jmp short show ok: pop es pop bx pop si pop cx pop dx retcode endsend start

3.运行结果:


实验分析结束,如果大家进行到这个阶段的话,想必DosBox和masm已经安装,后续课程设计2所需要的Windows xp镜像和综合研究阶段会使用的tc2.0我已经上传网盘,免费分享给大家,关注我的公众号,菜单栏–>技术相关–>免费资源即可领取,还有网课查答案,包括学习通、智慧树、mooc,内容涵盖计算机、政治等等,还有其他资源(简历模板、电子版书籍和考试资料等等),说不准大家会有用(分享干货)!

相关推荐

相关文章