彙編語言:課程設計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的原理就是向顯存中直接寫數據,如果之後數據被新內容覆蓋掉,哥就無能爲力了。

總結:

之前沒覺得彙編有多麻煩,甚至還天真地認爲只要把高級語言簡單翻譯一下,彙編程序就手到擒來了。我還是太天真了,彙編要注意的細枝末節太多,太瑣碎了,我寫出的程序也和垃圾沒什麼區別,反正每人認真看,我也只要能讓代碼運行就行了(這種思想很危險啊!!!)
其實在編程之前,我腦子中有個大概的框架和思路,用循環結構,每次輸出一行的內容,在一行中依次輸出需要得信息。但是一落實到代碼實現,又不得不考慮底層的機器,各種保護寄存器,各種尋址方式,各種方式傳參。最後形成的代碼就是一個個零散的“部件”,完全看不出我腦海中原本樸素而簡單的思想。總之,這次的程序設計,思路很簡單,但是實現起來較爲繁瑣,這麼簡單的程序居然寫了這麼長。我寫彙編的能力有了長足的進步(高興)。
最後,我需要寫兩天高級語言冷靜一下(笑)。

發佈了58 篇原創文章 · 獲贊 31 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章