1. 程式人生 > 其它 >38 外觀數列

38 外觀數列

組合語言實驗四

實驗任務1

在螢幕中間分別顯示綠色、綠底紅色、白底藍色的字串'welcome to masm'

task1.asm:

assume cs:code,ds:data
data segment
db 'welcome to masm!'
data ends
code segment 
start:mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
mov cx,16
mov bx,0
mov di,11*160+64;顯示視訊記憶體中的偏移量,11行64位元組的列偏移量
s1:mov al,ds:[bx]
mov ah,00000010b;設定顏色
mov es:[di],ax;設定數值
inc bx
add di,2
loop s1

mov cx,16
mov bx,0
mov di,12*160+64
s2:mov al,ds:[bx]
mov ah,00100100B
mov es:[di],ax
inc bx
add di,2
loop s2

mov cx,16
mov bx,0
mov di,13*160+64
s3:mov al,ds:[bx]
mov ah,01110001B
mov es:[di],ax
inc bx
add di,2
loop s3
code ends
end start

實驗結果:

實驗任務2

編寫子程式printStr,實現以指定顏色在螢幕上輸出字串、呼叫它完成字串輸出:
task2.asm:

assume cs:code, ds:data
data segment
    str db 'try', 0
data ends

code segment
start:  
    mov ax, data
    mov ds, ax

    mov si, offset str
    mov al, 2
    call printStr

    mov ah, 4ch
    int 21h

printStr:
    push bx
    push cx
    push si
    push di

    mov bx, 0b800H
    mov es, bx
    mov di, 0
s:    mov cl, [si]
    mov ch, 0
    jcxz over
    mov ch, al
    mov es:[di], cx
    inc si
    add di, 2
    jmp s

over:    pop di
    pop si
    pop cx
    pop bx
    ret

code ends
end start

實驗結果:

將line3改成:
str db 'another try',0

line 12改成:
mov al,4

結果:

基於執行結果,理解原始碼,以及,組合使用轉移指令call和ret實現子程式的原理與方法。具體地,在 line18-40中:

  • line19-22, line36-39,這組對稱使用的push、pop,這樣用的目的是什麼?

    • line 19-22是為了防止暫存器在子程式和主程式起衝突而設定的,以便在主程式中恢復原先的暫存器中的內容;line36-39就是暫存器內容恢復的過程
  • line30的功能是什麼?

    • line30是像實驗1中的一樣,將分別表示顏色和數值的cx送入視訊記憶體空間之中,以便顯示出來;

實驗任務3

使用任意文字編輯器,錄入彙編源程式task3.asm;

子程式num2str:

  • 功能:把0~2559之間的任意整數轉換成數字字串,例如,把1984轉換成'1984'
    • 入口引數 要轉換的整數 —> ax
    • 數字字串的起始地址 —> ds:di (其中:數字字串所在段的段地址—> ds,字串 起始地址的偏移地址—>di)
  • 出口引數:無

程式碼:

assume cs:code, ds:data
data segment
    x dw 1984
    str db 16 dup(0)
data ends

code segment
start:  
    mov ax, data
    mov ds, ax
    mov ax, x
    mov di, offset str
    call num2str
    mov si, offset str
    call printStr

    mov ah, 4ch
    int 21h

num2str:
    push ax
    push bx
    push cx
    push dx
    
    mov cx, 0
    mov bl, 10
s1:      
    div bl
    inc cx
    mov dl, ah
     push dx
    mov ah, 0
    cmp al, 0
       jne s1
s2:    
    pop dx
    or dl, 30h
    mov [di], dl
    inc di
    loop s2
    
    pop dx
    pop cx
    pop bx
    pop ax

    ret

printStr:
    push bx
    push cx
    push si
    push di

    mov bx, 0b800H
    mov es, bx
    mov di, 0
s:    mov cl, [si]
    mov ch, 0
    jcxz over
    mov ch, al
    mov es:[di], cx
    inc si
    add di, 2
    jmp s

over:    pop di
    pop si
    pop cx
    pop bx
    ret

code ends
end start

子任務1

對task3.asm進行彙編、連結,得到可執行程式後,在debug中使用u命令反彙編,使用g命令執行 到line15(程式退出之前),使用d命令檢視資料段內容,觀察是否把轉換後的數字字串'1984'存放 在資料段中str標號後面的單元。

debug結果如下:

子任務2

對task3.asm原始碼進行修改、完善,把task2.asm中用於輸出以0結尾的字串的子程式加進來, 實現對轉換後的字串進行輸出。

程式碼:

assume cs:code, ds:data
data segment
    x dw 1984
    str db 16 dup(0)
data ends

code segment
start:  
    mov ax, data
    mov ds, ax
    mov ax, x
    mov di, offset str
    call num2str
    mov si, offset str
    call printStr

    mov ah, 4ch
    int 21h

num2str:
    push ax
    push bx
    push cx
    push dx
    
    mov cx, 0
    mov bl, 10
s1:      
    div bl
    inc cx
    mov dl, ah
     push dx
    mov ah, 0
    cmp al, 0
       jne s1
s2:    
    pop dx
    or dl, 30h
    mov [di], dl
    inc di
    loop s2
    
    pop dx
    pop cx
    pop bx
    pop ax

    ret

printStr:
    push bx
    push cx
    push si
    push di

    mov bx, 0b800H
    mov es, bx
    mov di, 11*160+64
s:    mov cl, [si]
    mov ch, 0
    jcxz over
    mov ch, al
    mov es:[di], cx
    inc si
    add di, 2
    jmp s

over:    pop di
    pop si
    pop cx
    pop bx
    ret

code ends
end start

效果:

修改line3的值效果:

可以看出顏色是由暫存器al中的資料所控制;

實驗任務4

使用任意文字編輯器,錄入彙編源程式task4.asm。

程式碼:

assume cs:code, ds:data
data segment
    str db 80 dup(?)
data ends

code segment
start:  
    mov ax, data
    mov ds, ax
    mov si, 0

s1:    
    mov ah, 1
    int 21h
    mov [si], al
    cmp al, '#'
    je next
    inc si
    jmp s1
next:
    mov cx, si
    mov si, 0
s2:     mov ah, 2
    mov dl, [si]
    int 21h
    inc si
    loop s2

    mov ah, 4ch
    int 21h
code ends
end start

效果截圖:

line12-19行的作用是:讀入字元,直到遇見#為止;

line21-27實現的作用是:輸出從鍵盤輸入的字串;

實驗任務5

在visual studio整合環境中,編寫一個簡單的包含有函式呼叫的c程式。程式碼如下:

#include<stdio.h>
int sum(int, int);
int main()
{
    int a=2,b=7,c;
    
    c=sum(a,b);
    
    return 0;
}
int sum(int x,int y)
{
    return (x+y);
}

在line7, line13分別設定斷點,在除錯模式下,檢視反彙編程式碼。

分析反彙編程式碼,從彙編的角度,觀察高階語言中引數傳遞和返回值是通過什麼實現的,以及,引數入 棧順序,返回值的帶回方式,等等。

從上面的彙編程式碼我們可以看到,在函式的入口,將[b]和[a]中的值先後push進棧中,然後通過call命令跳轉到sum函式處。待函式完成後通過mov指令,將eax賦值給[c]完成函式運算。

int sum到return (x+y)的反彙編程式碼我們可以看出,顯示將重要的暫存器入棧保護,return操作就是將[x]的值加到[y]中去,然後暫存器出棧進行暫存器恢復,然後ret返回主函式,完成運算。

實驗結論

  • 本次實驗使我瞭解了此程式的編寫過程,以及8086中80*25彩色模式的顯示原理。
  • 能夠熟練的使用jmp、loop、jcxz等跳轉指令,根據跳轉的不同原理完成各項功能。
  • 能夠綜合使用ret、call、je、jz、cmp等指令完成綜合的子程式,迴圈分支結構程式碼的編寫。
  • 通過對c語言的返彙編實驗,將彙編與高階語言結合起來,更加加深了對組合語言的理解。