《組合語言》王爽 課程設計1
阿新 • • 發佈:2018-12-10
將實驗7的資料顯示在螢幕上:
分析:先將 data 中的資料轉換成字串後儲存在 table 中再顯示,按行顯示
遇到的問題:loop迴圈中的程式程式碼太長,loop對IP的修改範圍(-128~127Bytes),導致編譯無法通過,所以將loop換成以下語句
m_loop:
;some code
...
dec cx
jcxz b_loop
jmp m_loop
b_loop:
mov ax, 4c00H
int 21H
具體程式碼:
;《組合語言》課程設計1 ;按行顯示,共21行,迴圈21次,cx迴圈計數 ;每行按 "年份"、"總收入"、"僱員數"、"平均收入" 順序顯示 ;將每一行的資料轉換成字串儲存到table,再顯示 assume cs:code, ds:data, ss:stack data segment ;21個年份,84個byte db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983' db '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992' db '1993', '1994', '1995' ;21年總收入,84個byte dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514 dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000 ;21年僱員人數,42個byte dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226 dw 11542, 14430, 15257, 17800 ;21年人均收入, dw 5, 3, 42, 104, 85, 210, 123, 111, 105, 125, 140, 136, 153, 211, 199, 209, 224, 239 dw 260, 304, 333 data ends table segment db 32 dup (0) table ends stack segment db 32 dup (0) stack ends code segment start: mov ax, data mov es, ax ;(es): data段地址 mov ax, table mov ds, ax ;(ds): table段地址 mov ax, stack mov ss, ax mov sp, 20H ;初始化棧 mov cx, 21 ;迴圈計數21次,1次迴圈顯示一行 mov dh, 2 ;顯示的起始行 mov dl, 2 ;顯示的起始列 mov si, 0 mov di, 0 m_loop: ;主迴圈 push cx ;儲存當前迴圈數 push dx ;儲存當前顯示行列 push di ;(di) = 當前行 mov bp, sp ;(bp) = (sp),即(ss:[bp] = di) ;年份 mov si, 0 mov al, 4 mov bl, byte ptr [bp] call get_offset mov cx, 4 y_loop: ;年份迴圈 mov al, es:[di] mov ds:[si], al inc di inc si loop y_loop mov byte ptr ds:[si], 0 ;年份結尾標誌 mov dx, [bp+2] ;(dx) = (ss:[bp+2]) mov cl, 2 ;(cl) = 2,字型顏色 call show_str ;總收入dword型,資料起始位置es:[84] mov al, 4 mov bl, byte ptr [bp] call get_offset mov ax, es:[di+84] ;總收入低16位 mov dx, es:[di+86] ;總收入高16位 call dtoc mov dx, [bp+2] mov dl, 12 mov cl, 2 call show_str ;僱員人數word型,資料起始位置es:[168] mov al, 2 mov bl, byte ptr [bp] call get_offset mov ax, es:[di+168] ;word型,進行divw除法,ax為低16位 mov dx, 0 ;dx為高16位,置0 call dtoc mov dx, [bp+2] mov dl, 22 mov cl, 2 call show_str ;平均收入word型,資料起始位置es:[210] mov al, 2 mov bl, byte ptr [bp] call get_offset mov ax, es:[di+210] mov dx, 0 call dtoc mov dx, [bp+2] mov dl, 32 mov cl, 2 call show_str pop di pop dx pop cx inc di ;下一行 inc dh ;下一行顯示起始位置,行 + 1,列不變 dec cx jcxz b_loop jmp m_loop b_loop: mov ax, 4c00H int 21H ;子程式描述 ;名稱:show_str ;功能:在指定的位置用指定的顏色,顯示一個以0結尾的字串 ;引數:(dh) = 行號(取值範圍:0~24),(dl) = 列號(取值範圍:0~79) ; (cl) = 顏色,ds:[si]指向字串的首地址 ;返回:無 show_str: push es push ax push bx mov si, 0 mov ax, 0b800H mov es, ax mov ah, 0 mov al, 160 mul dh mov bx, ax mov ah, 0 mov al, 2 mul dl add bx, ax ;es:[bx]為顯示起始地址 mov al, cl mov ch, 0 show_0: mov cl, ds:[si] jcxz show_1 ;判斷是否為字串結尾標誌0 mov es:[bx], cl mov es:[bx+1], al inc si add bx, 2 jmp show_0 show_1: pop bx pop ax pop es ret ;子程式描述 ;名稱:divdw ;功能:進行不會產生溢位的除法運算,被除數為dword型,除數為word型, ; 結果為dword型 ;引數:(ax) = dword型低16位,(dx) = dword型高16位,(cx) = 除數 ;返回:(dx) = 結果的高16位,(ax) = 結果的低16位,(cx) = 餘數 divw: push ax mov ax, dx ;先進行高16位除法 mov dx, 0 div cx ;餘數在(dx)中,商在(ax)中 mov bx, ax ;將高位商在(bx)中儲存 pop ax ;再進行低16位除法 div cx ;餘數在(dx)中,商在(ax)中 mov cx, dx mov dx, bx ;(dx) = 結果高16位,(ax) = 結果低16位,(cx) = 餘數 ret ;子程式描述 ;名稱:dtoc ;功能:將資料轉化為字串,字串以0結尾 ;引數:(dx) = dword型高16位, ; (ax) = dword型低16位, ; ds:[si]指向字串的首地址 ;返回:無 dtoc: mov si, 0 mov bx, 0 push bx ;字串結尾標誌入棧 dtoc_0: mov cx, 10 ;(cx) = 除數 call divw add cx, 30H ;餘數 + 30H = 對應的字元ASCII碼 push cx mov cx, dx ;判斷高位商是否為0 jcxz dtoc_1 ;為0繼續判斷低位商 dtoc_1: mov cx, ax ;判斷低位商是否為0 jcxz dtoc_2 ;為0則表示除盡,進行轉字串操作 jmp dtoc_0 ;否則繼續進行除法 dtoc_2: pop cx mov ds:[si], cl ;將字串傳入(ds)中 jcxz dtoc_3 inc si jmp dtoc_2 dtoc_3: mov si, 0 ret ;子程式描述 ;名稱:get_offset ;功能:獲取資料相對偏移位置 ;引數:(al) = 資料型別長度 ; (bl) = 該類資料的第幾個 ;返回:無 get_offset: mov ah, 0 mul bl mov di, ax ;(di) = 相對該型別資料初始位置的偏移 ret code ends end start
執行結果:
歡迎討論!