汇编语言:课程设计1

汇编语言:课程设计1

本文内容来源于王爽《汇编语言(第3版)》

任务

将实验7(见原书)中Power idea 公司的数据按照如下格式在屏幕上显示出来。
这里写图片描述

提示

注意:有些数据已经超过16位了,因此要写一个新的子程序dtoc(见我的上一篇博文,或者见原书),我把它命名为ddtoc(详细信息见源代码,如果你看得懂我的中式英语的话)。在实现的过程中,要注意除法溢出的问题,因此还要调用自己之前实现的divdw子程序(见我的上一篇博文,或者见原书)
实现代码如下:

;---------------------------------------------------------------------
;proc_name: ddtoc
;function:  translate dword type data into a decimal string which
;           ends with 0
;interface: (ax) = the low 16 bit of the dword type data
;           (dx) = the high 16 bit of the dword type data
;           ds:si points to the first address of the string
;return:    void
ddtoc:          push    ax
                push    cx
                push    dx
                push    si
                push    bp

                mov     bp,sp
    ddtoc_s:    mov     cx,10
                call    divdw
                add     cx,'0'
                push    cx
                mov     cx,dx
                add     cx,ax
                jcxz    ddtoc_next
                jmp     short ddtoc_s

    ddtoc_next: pop     ax
                mov     [si],al
                mov     cx,sp
                sub     cx,bp
                jcxz    ddtoc_ok
                inc     si
                jmp     short ddtoc_next

    ddtoc_ok:   mov     al,0
                mov     [si+1],al

                pop     bp
                pop     si
                pop     dx
                pop     cx
                pop     ax
                ret
;--------------------------------------------------------------------------
;proc_name: divdw
;function:  Division operation(avoid overflow)
;           the dividend is dword type and the divisor is word type
;           the result is dword type, the remainder is word type.
;interface: (ax) = the low 16 bit of the dividend
;           (dx) = the high 16 bit of the dividend
;           (cx) = divisor(word type)
;return:    (dx) = the high 16 bit of the result
;           (ax) = the low 16 bit of the result
;           (cx) = the remainder
divdw:      push    dx
            push    ax
            push    bp

            mov     bp,sp
            mov     dx,0
            mov     ax,[bp+4]
            div     cx
            push    ax
            mov     ax,[bp+2]
            div     cx
            mov     cx,dx
            pop     dx

            pop     bp
            add     sp,4
            ret
;-----------------------------------------------------------------------------

代码实现

下面给出这个程序的完整代码:
附:由于汇编程序太过琐碎,就不给详细注释了,因为这段代码本身就是垃圾,各位看官扫一眼就可以,最后的效果之后给出(绝对辣眼睛!!!)
就算是给子程序传递参数,我也遇到了寄存器冲突问题,没办法,只能用堆栈保护。子程序show_str,dtoc都要有一段内存空间存放数据,因此我在table段后面放了20个字节的空间。
总而言之,代码乱的很,根本没法看,调试也极其困难,好歹运气好,满足了课程要求(吗?)

assume      cs:code,ss:stack

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'
  ;offset address range:0-53h. informations of the years
  dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
  dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
  ;offset address range:54h-0a7h. information of the gross income each year
  dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
  dw 11542,14430,15257,17800
  ;offset address range:0a8h-0d1h.information of the number of the emploees each year
data ends

stack       segment
    db  256 dup(0)
stack       ends

table   segment
    db 21 dup('year',0,'summ',0,'ne',0,'??',0) 
    ;offset address range:0~14fh
    db 20 dup(?)
    ;each line has 16byte space
table   ends

code        segment

main:       mov     ax,data
            mov     ds,ax
            mov     ax,stack
            mov     ss,ax
            mov     sp,256

            call    load_info

            mov     ax,table
            mov     ds,ax

            mov     dh,0
            mov     bx,0
            mov     cx,21
    s0:     push    cx
            ;print the year
            mov     si,bx
            mov     dl,12
            mov     cl,00000111b
            call    show_str

            mov     si,150h
            ;print the gross income
            add     dl,12
            push    dx
            add     bx,5
            mov     ax,[bx]
            mov     dx,[bx+2]
            call    ddtoc
            pop     dx
            call    show_str
            ;print the number of the emploees each year
            add     dl,12
            push    dx
            add     bx,5
            mov     dx,0
            mov     ax,[bx]
            call    ddtoc
            pop     dx
            call    show_str
            ;print the average income
            add     dl,12
            push    dx
            add     bx,3
            mov     dx,0
            mov     ax,[bx]
            call    ddtoc
            pop     dx
            call    show_str

            inc     dh
            add     bx,3
            pop     cx
            loop    s0

            mov     ax,4c00h
            int     21h
;---------------------------------------------------------------
load_info:  
                push    ax
                push    bx
                push    cx
                push    dx
                push    si
                push    ds
                push    es

                mov     ax,data
                mov     ds,ax
                mov     ax,table
                mov     es,ax
                ;load the years
                mov     si,0
                mov     bx,0
                mov     cx,21

    load_info_s0: 
                mov     ax,[si]                 ;load the former 2 bytes
                mov     es:[bx],ax      

                mov     ax,[si+2]
                mov     es:[bx+2],ax            ;load the latter 2 bytes
                add     si,4

                add     bx,10h
                loop    load_info_s0
                ;load the gross income
                mov     si,54h
                mov     bx,0
                mov     cx,21

    load_infor_s1: 
                mov     ax,[si]                 ;load the former 2 bytes
                mov     es:[bx+5],ax

                mov     ax,[si+2]                ;load the latter 2 bytes
                mov     es:[bx+5+2],ax
                add     si,4

                add     bx,10h
                loop    load_infor_s1
                ;load the number of the emploees
                mov     si,0a8h
                mov     bx,0
                mov     cx,21

    load_infor_s2: 
                mov     ax,[si]
                mov     es:[bx+0ah],ax
                add     si,2

                add     bx,10h
                loop    load_infor_s2
                ;calculate and load the average income

                mov     bx,0
                mov     cx,21

            s3: mov     ax,es:[bx+5]
                mov     dx,es:[bx+5+2]
                div     word ptr es:[bx+0ah]
                mov     es:[bx+0dh],ax

                add     bx,10h
                loop    s3

                pop     es
                pop     ds
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                ret     
;---------------------------------------------------------------------
;proc_name: ddtoc
;function:  translate dword type data into a decimal string which
;           ends with 0
;interface: (ax) = the low 16 bit of the dword type data
;           (dx) = the high 16 bit of the dword type data
;           ds:si points to the first address of the string
;return:    void
ddtoc:          push    ax
                push    cx
                push    dx
                push    si
                push    bp

                mov     bp,sp
    ddtoc_s:    mov     cx,10
                call    divdw
                add     cx,'0'
                push    cx
                mov     cx,dx
                add     cx,ax
                jcxz    ddtoc_next
                jmp     short ddtoc_s

    ddtoc_next: pop     ax
                mov     [si],al
                mov     cx,sp
                sub     cx,bp
                jcxz    ddtoc_ok
                inc     si
                jmp     short ddtoc_next

    ddtoc_ok:   mov     al,0
                mov     [si+1],al

                pop     bp
                pop     si
                pop     dx
                pop     cx
                pop     ax
                ret
;--------------------------------------------------------------------------
;proc_name: divdw
;function:  Division operation(avoid overflow)
;           the dividend is dword type and the divisor is word type
;           the result is dword type, the remainder is word type.
;interface: (ax) = the low 16 bit of the dividend
;           (dx) = the high 16 bit of the dividend
;           (cx) = divisor(word type)
;return:    (dx) = the high 16 bit of the result
;           (ax) = the low 16 bit of the result
;           (cx) = the remainder
divdw:      push    dx
            push    ax
            push    bp

            mov     bp,sp
            mov     dx,0
            mov     ax,[bp+4]
            div     cx
            push    ax
            mov     ax,[bp+2]
            div     cx
            mov     cx,dx
            pop     dx

            pop     bp
            add     sp,4
            ret
;-----------------------------------------------------------------------------
;proc_name: show_str
;function:  output a string with one color in a certain postion  
;interface: (dh) = row(0~24),(dl) = column(0~79)
;           (cl) = color, ds:si points to the first address of the string
;return:    void
show_str:       push    ax
                push    bx
                push    cx
                push    dx
                push    es
                push    si

                mov     ax,0b800h
                mov     es,ax
                ;set row
                mov     al,160
                mul     dh
                mov     bx,ax
                ;set column
                mov     dh,0
                add     dx,dx
                mov     di,dx
                ;output the string
                mov     ah,cl
show_str_s:     mov     al,[si]
                mov     ch,0
                mov     cl,al
                jcxz    show_str_ok
                mov     es:[bx+di],ax
                inc     si
                add     di,2
                jmp     short show_str_s

show_str_ok:    pop     si
                pop     es
                pop     dx
                pop     cx
                pop     bx
                pop     ax      
                ret
;------------------------------------------------------------------------

code        ends

end     main

输出的结果是这样的
这里写图片描述

这是什么鬼!怎么还有数据被”press any key to continue”覆盖掉了!
这是目前阶段没有办法避免的(按部就班地按照课本内容学习的话)。子程序show_str的原理就是向显存中直接写数据,如果之后数据被新内容覆盖掉,哥就无能为力了。

总结:

之前没觉得汇编有多麻烦,甚至还天真地认为只要把高级语言简单翻译一下,汇编程序就手到擒来了。我还是太天真了,汇编要注意的细枝末节太多,太琐碎了,我写出的程序也和垃圾没什么区别,反正每人认真看,我也只要能让代码运行就行了(这种思想很危险啊!!!)
其实在编程之前,我脑子中有个大概的框架和思路,用循环结构,每次输出一行的内容,在一行中依次输出需要得信息。但是一落实到代码实现,又不得不考虑底层的机器,各种保护寄存器,各种寻址方式,各种方式传参。最后形成的代码就是一个个零散的“部件”,完全看不出我脑海中原本朴素而简单的思想。总之,这次的程序设计,思路很简单,但是实现起来较为繁琐,这么简单的程序居然写了这么长。我写汇编的能力有了长足的进步(高兴)。
最后,我需要写两天高级语言冷静一下(笑)。

原文地址:https://www.cnblogs.com/wyf12138/p/6581528.html