汇编语言课程设计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,17800
data1 ends  
table segment  
    db 21 dup ('year summ ne ?? ')  
table ends
data segment
    db 10 dup (0)
data ends
code segment
start: 
        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

            ret

divdw:                    

        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)

        ret

cls:        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            

            ret

show_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            

            ret

code ends

end start

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值