8086匯編(32)將之前的Power idea公司的數(shù)據(jù)按照下圖所示的格式在屏幕上顯示出來。

將之前的Power idea公司的數(shù)據(jù)按照下圖所示的格式在屏幕上顯示出來。

圖片.png

之前的文章

示例代碼如下:

assume cs:codesg 
                                                   ;將整個data段看作是一個數(shù)組,長度一共為 
                                                     ;21*4+21*4+2*21=168+42=210字節(jié) 

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'                     ;長度為84的數(shù)組,一個字符一個字節(jié):4X21 
    dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514 dd 345980, 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 
data ends                            ;ax+210/16向上取整,即ax+14h ;對于ds,偏移量為16*14=224 

table segment 
     db 21 dup('year summ ne ?? ') 
table ends 

show segment 
     db 100 dup(0) 
show ends 

temp segment 
     dw 10 dup(0) 
temp ends 

codesg segment 
start:      mov ax, data 
            mov ds, ax 
            mov bx, table 
            mov es, bx 
            mov bx, 0 ;定位結構體數(shù)組元素 
            mov di, 0 ;定位data中的4字節(jié)數(shù)據(jù) 
            mov si, 0 ;定位data中的2字節(jié)數(shù)據(jù) 
            mov cx, 15h s0: ;轉移年份 
            mov ax, ds:[di]; 
            mov es:[bx], ax 
            mov ax, ds:[di+2] 
            mov es:[bx+2], ax ;添加空格 
            mov byte ptr es:[bx+4], 32 ;轉移收入 ;作為被除數(shù) 
            mov ax, ds:[di+84]; 
            mov es:[bx+5], ax 
            mov ax, ds:[di+86] 
            mov es:[bx+7], ax ;添加空格 
            mov byte ptr es:[bx+9], 32 ;轉移雇員數(shù)量 
            mov ax, ds:[si+168] 
            mov es:[bx+10], ax ;添加空格 
            mov byte ptr es:[bx+12], 32 ;計算人均收入,并轉移到table中 
            mov ax, es:[bx+5] ;低16位 
            mov dx, es:[bx+7] ;高16位 
            div word ptr es:[bx+10] 
            mov es:[bx+13], ax ;商默認存放在ax中 ;添加空格 
            mov byte ptr es:[bx+15], 32 ;操作完成,bx加16,di加2 
            add bx, 16 
            add di, 4 
            add si, 2 
            loop s0 ;s0循環(huán)的作用主要是將數(shù)據(jù)存儲到table段中 ;而在s1循環(huán)中,先把table段中的數(shù)據(jù)轉化為字符串,轉儲到 ;show段中,然后再在s2循環(huán)中調(diào)用show_str子程序來將這些字符串一行一行地 ;顯示到屏幕上 
            mov ax, table 
            mov ds, ax 
            mov ax, show 
            mov es, ax 
            mov dx, 0 
            mov dh, 4 
            mov bx, 0 
            mov cx, 15h 

s1: 
            mov di, 0 ;這里的di作為table數(shù)據(jù)段的指針 
            push ds 
            push es 
            push cx 
            push dx ;保存行列信息,在調(diào)用show_str時會用到 ;轉儲年份 
            mov ax, ds:[bx+di] 
            mov es:[di], ax 
            add di, 2 
            mov ax, ds:[bx+di] 
            mov es:[di], ax 
            mov byte ptr es:[di+4], 0 ;轉儲收入 
            mov di, 5 
            mov ax, ds:[bx+di] 
            mov dx, ds:[bx+di+2] 
            call dtoc ;轉儲人數(shù) 
            mov ax, ds:[bx+10] 
            mov dx, 0 
            call dtoc ;轉儲人均收入 
            mov ax, ds:[bx+13] 
            mov dx, 0 
            call dtoc ;以上就是table段中的一行轉換為ASCII碼值的處理過程 ;下面開始顯示過程,此過程需要循環(huán)四次 
            pop dx 
            mov di, 0 ;這里的di作為待輸出數(shù)據(jù)段的指針 
            mov cx, 4 

s2: 
            mov si, 0 
            call show_str 
            add dl, 20 ;把列錯開 
            loop s2 
            mov dl, 0 
            add dh, 1 
            add bx, 16 
            pop cx 
            pop es 
            pop ds 
            loop s1 
            mov ax, 4c00h 
            int 21h 

dtoc: 
;該子程序用于將數(shù)值型的數(shù)字轉換為字符串 ;十進制數(shù)值轉換為ASCII碼值,轉換關系為:ascii=10進制+30H ;要想將一個十進制的整數(shù)拆分成一個一個的數(shù)值,那我們需要讓這個數(shù) ;除以10,然后將得到的結果依次入棧,除完之后再依次出棧,即可得到由高位到低位 ;的所有數(shù)值,之后將這些值加上30H,即得到其對應的ASCII碼值,然后將這些 ;ASCII碼值存放到一個數(shù)據(jù)段中,調(diào)用show_str函數(shù),來在屏幕上顯示這些數(shù)值 ;為了存儲轉換后的ASCII碼值,我們需要新開辟一個數(shù)據(jù)段 
             push bx 
             push cx 
             push dx 
             push ds 
             push ax 
             push si 
             push es 
             mov bx, 0 ;記錄十進制數(shù)據(jù)的位數(shù) 

split: 

             mov cx, 0ah ;cx存放除數(shù)
             call divdw ;如果被除數(shù)大于2550,al是無法存放商的,會造成溢出,因此,我們需要調(diào)用本實驗中第二個程序 ;專門用于解決除法溢出問題的程序 ;此程序返回運算后的商和余數(shù),分別保存在ax和cx中 
             push cx ;余數(shù)入棧 
             inc bx ;當循環(huán)終止的時候可以進行彈棧存儲操作了,但是我們需要一個標記,來標識我們需要 ;彈出多少次,我們使用bx來進行存儲 
             mov cx, ax 
             add cx, dx ;ax中的值在下一次運算中一定會用到,dx中的值也有可能會用到(當被除數(shù)很大時) ;此時可以臨時保存數(shù)據(jù)的只有cx了,因此我們直接將運算結果放到cx中 ;一舉兩得 ;判斷條件是商==0,因此我么需要高16位和低16位全都為0 
             jcxz ok1 ;處理過程是需要循環(huán)的,循環(huán)結束的條件是商==0 ;我們只需要將執(zhí)行jcxz指令即可,當cx的值位0的時候,它會自動跳轉到ok1循環(huán)的 
             jmp short split 

ok1: 
             pop ax 
             add al, 30h 
             mov byte ptr es:[di], al 
             inc di dec bx 
             mov cx, bx 
             jcxz last
 
             jmp short ok1


last: 
;最后一步,在數(shù)據(jù)的ASCII數(shù)據(jù)形式的最后加上一個0 
             mov ah, 0
             mov byte ptr es:[di], ah 
             inc di 
             pop es 
             pop si 
             pop ax 
             pop ds 
             pop dx 
             pop cx 
             pop bx 
             ret 

divdw: 
              push ds 
              push dx 
              push cx 
              push bx 
              push ax 
              mov ax, temp 
              mov ds, ax 
              mov ax, dx 
              mov dx, 0 
              div cx ;ax存放商,dx存放余數(shù) ;根據(jù)公式,使用被除數(shù)高位除以除數(shù)得到的商×65536 ;*65536等價于在低位加16個0,因此操作就會變得非常簡單 ;使用被除數(shù)高位除以除數(shù)得到的余數(shù)×65536+被除數(shù)的低位,再將得到的結果除以除數(shù) ;兩者的結果相加,即可得到32位/16位的無溢出結果 push dx ;使用棧臨時保存余數(shù) 
              mov dx, ax 
              mov ax, 0 
              mov ds:[0], ax 
              mov ds:[2], dx 
              pop dx ;彈出余數(shù),作為右操作數(shù)中被除數(shù)的高16位 pop ax ;得到被除數(shù)的低16位 push ax ;恢復棧頂數(shù)據(jù),避免對主程序造成干擾 ;將右操作數(shù)[]中的左操作數(shù)的低16位和被除數(shù)的低16位相加 ;但是右操作數(shù)[]中的左操作數(shù)的低16位一定是全0的,因此我們可以省略這一步 ;直接執(zhí)行pop ax,將被除數(shù)的低16位作為右操作數(shù)的低16位 div cx ;ax存放商,dx存放余數(shù) ;由于左操作數(shù)的低16位一定是全0,所以不必與其相加,直接將 ;右操作數(shù)的低16位存儲到ds:[0]內(nèi)存單元即可 
              mov ds:[0], ax ;商的低16位放到ds:[0]單元中 mov ds:[4], dx ;余數(shù)放到ds:[4]單元中 ;ds:[2]中一直保存的都是商的高16位,且沒有被更改過,因此無須任何操作 
              pop ax 
              pop bx 
              pop cx 
              pop dx 
              mov ax, ds:[0] ;ax保存商的低16位 
              mov dx, ds:[2] ;dx保存商的高16位 
              mov cx, ds:[4] ;cx保存余數(shù) pop ds ;之所以要在pop ds之前將數(shù)據(jù)轉移,是因為子程序divdw調(diào)用前,ds已經(jīng)被使用 ;指向的是其他的段,如果不在pop之前轉移數(shù)據(jù),那么div段的數(shù)據(jù)就無法獲取了 
              ret 

show_str: 
              push ax 
              push bx 
              push cx 
              push dx 
              push es 
              push ds ;根據(jù)上節(jié)中的框架,為了不讓子程序干擾主程序中寄存器的值,將所有子程序會用到的寄存器進行壓棧 
              mov ax, 0b800h 
              mov es, ax ;顏色區(qū)的段地址 
              mov ax, show 
              mov ds, ax ;要讀入的數(shù)據(jù)區(qū)的段地址 
              mov al, 160 
              mul dh ;每行占160個字節(jié),乘以行數(shù) 
              push ax ;將行計算的結果存儲到棧中 
              mov al, 2 
              mul dl ;每列占2個字節(jié),乘以列數(shù) 
              pop bx ;將上次運算的結果(160×行數(shù))的值轉移到bx中 add bx, ax ;此時的ax值為(2×列數(shù)) ;將兩者相加,最終結果保存到bx中 
              mov dl, 130 ;顯示顏色為綠色 

change:
              mov cl, ds:[di] 
              inc di 
              mov ch, 0 
              jcxz ok 
              mov ch, dl 
              mov es:[bx+si], cx 
              add si, 2 
              jmp short change 

ok: 
               pop ds 
               pop es 
               pop dx 
               pop cx 
               pop bx 
               pop ax 
               ret 
codesg ends 
end start

參考鏈接: https://blog.csdn.net/include_heqile/article/details/80629599

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容