實驗2 多個邏輯段的匯編源程序編寫與調試


多個邏輯段的匯編源程序編寫與調試

實驗任務1

  • 任務1-1

    對程序task1_1.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。

    assume ds:data, cs:code, ss:stack
    
    data segment
        db 16 dup(0)
    data ends
    
    stack segment
        db 16 dup(0)
    stack ends
    code segment
    start:
        mov ax, data
        mov ds, ax
    
        mov ax, stack
        mov ss, ax
        mov sp, 16
    
        mov ah, 4ch
        int 21h
    code ends
    end start
    

    問題1:
    查看寄存器值
    使用U命令查看反匯編代碼,找到mov ah,4ch這一代碼的內存地址,並使用G命令快速執行到這條命令之前。

    (DS)=076C
    (SS)=076D
    (CS)=076E

    問題2:
    假設程序加載后,CODE段地址為X,則data段地址為X-2,stack段地址為X-1
    由於程序占用的內存空間是連續的,又由於段大小占16字節的整數倍,所以如果按照task1-1.ASM的代碼,data緊挨着程序段前綴,stack緊挨着data,code緊挨着stack。

  • 任務1-2
    對程序task1_2.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。

    assume ds:data, cs:code, ss:stack
    data segment
        db 4 dup(0)
    data ends
    
    stack segment
        db 8 dup(0)
    stack ends
    code segment
    start:
        mov ax, data
        mov ds, ax
    
        mov ax, stack
        mov ss, ax
        mov sp, 8
    
        mov ah, 4ch
        int 21h
    code ends
    end start
    

    問題1:
    重復task1-1的問題1的操作,查看寄存器值

    (DS)=076C
    (SS)=076D
    (CS)=076E

    問題2:
    假設程序加載后,CODE段地址為X,則data段地址為X-2,stack段地址為X-1
    由於程序占用的內存空間是連續的,又由於段大小占16字節整數倍,所以如果按照task1-2.ASM的代碼,data緊挨着程序段前綴,stack緊挨着data,code緊挨着stack。

  • 任務1-3
    對程序task1_3.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。

    assume ds:data, cs:code, ss:stack
    data segment
    db 20 dup(0)
    data ends
    stack segment
    db 20 dup(0)
    stack ends
    code segment
    start:
    mov ax, data
    mov ds, ax
    
    mov ax, stack
    mov ss, ax
    mov sp, 20
    
    mov ah, 4ch
    int 21h
    code ends
    end start
    

    問題1:
    重復task1-1和task1-2的操作,結果如下

    (DS)=076C
    (SS)=076E
    (CS)=0770

    問題2:
    假設程序加載后,CODE段地址為X,則data段地址為X-4,stack段地址為X-2
    由於程序占用的內存空間是連續的,又由於段大小占16字節整數倍,所以如果按照task1-3.ASM的代碼,data緊挨着程序段前綴,stack緊挨着data,code緊挨着stack。

  • 任務1-4
    對程序task1_4.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。

    assume ds:data, cs:code, ss:stack
    code segment
    start:
    mov ax, data
    mov ds, ax
    
    mov ax, stack
    mov ss, ax
    mov sp, 20
    
    mov ah, 4ch
    int 21h
    code ends
    
    data segment
    db 20 dup(0)
    data ends
    
    stack segment
    db 20 dup(0)
    stack ends
    end start
    

    問題1:
    重復操作,查看寄存器值

    (DS)=076E
    (SS)=0770
    (CS)=076C

    問題2:
    假設程序加載后,CODE段地址為X,則data段地址為X+2,stack段地址為X+4
    由於程序占用的內存空間是連續的,又由於段大小占16字節整數倍,所以如果按照task1-4.ASM的代碼,code緊挨着程序段前綴,data緊挨着code,stack緊挨着data。
    這里的情況很特殊,一般的段空間,由於8086尋址的特性,都是16的整數倍,但是這里的stack段,由於stack下面沒有其他段,猜測當時為了節省內存空間,沒有分配16的整數倍空間,而是要多少分配多少。具體實踐如下圖

    • 查看最后段的段空間分配情況
    • 查看task1-1,task1-2,task1-3 code段后的內存分配情況

      可以看到並非為0
  • 任務1-5
    基於上述四個實驗任務的實踐、觀察,總結並回答:
    問題1:
    對於如下定義的段,程序加載后,實際分配給該段的內存空間大小是
    當本段不是程序的最后一段時: \(\lceil \frac{N}{16} \rceil \times 16\)
    當本段是程序的最后一段時: \(N\)

    xxx segment
    db N dup(0)
    xxx ends
    

    問題2:
    如果將程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,偽指令 end start 改成end , 哪一個程序仍然可以正確執行?結合實踐觀察得到的結論,分析、說明原因。
    注意:本處正常執行指的是從start標號處開始執行,沒從start標號處執行均視為不能正常執行

    • 程序task1-1.ASM

      不能正常執行
    • 程序task1-2.ASM

      不能正常執行
    • 程序task1-3.ASM

      不能正常執行
    • 程序task1-4.ASM

      可以正常執行
    • 分析
      匯編器在處理匯編源程序的時候會先處理偽指令。start偽指令表示程序段從此處開始,會將code segment給CS段寄存器。由於startend start需要成對出現,匯編器找到start后,卻沒找到end start,所以start無效,因此從程序段前綴之后開始執行程序,由於1,2,3個子任務的程序段前綴之后都是數據段,因為在8086匯編環境下,數據和指令處於同等地位,所以CPU無法辨別內存中的是指令還是數據,所以1,2,3個子任務不能正確完成期望的代碼的執行。

實驗任務2

編寫一個匯編源程序,實現向內存單元b800:0f00 ~ b800:0f9f連續160字節,依次重復填充十六進制數據03 04
代碼如下:

assume cs:code
code segment
start:     
    mov ax,0b800h
    mov ds,ax
    mov bx,0f00h
    mov cx,80
p:
    mov ds:[bx],0403h
    inc bx
    inc bx
    loop p

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

運行結果如下:

注意事項:
數字要以數字開頭,所以b800h要寫成0b800h,f00h同理,要寫成0f00h
03 04 也需要注意,03是低位,04是高位,所以應該存0403h。

實驗任務3

已知8086匯編源程序task3.asm代碼片段如下。

assume cs:code
data1 segment
    db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends

data2 segment
    db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0       ; ten numbers
data2 ends

data3 segment
    db 16 dup(0)
data3 ends

code segment
start:
   ; ×××
code ends
end start

要求:
① 編程實現把邏輯段data1和邏輯段data2的數據依次相加,結果保存到邏輯段data3中。
② 在debug中加載、反匯編、調試。在數據項依次相加前,和相加后,分別查看三個邏輯段data1,
data2, data3對應的內存空間,確認逐一相加后,結果的確保存在了邏輯段data3中。

問題1:
源代碼如下:

assume cs:code
data1 segment
    db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends

data2 segment
    db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0       ; ten numbers
data2 ends

data3 segment
    db 16 dup(0)
data3 ends

code segment
start:
    mov ax,data1
    mov ds,ax
    mov cx,16
    mov bx,0
s:  
    mov al,ds:[bx]
    add al,ds:[bx+16]
    mov ds:[bx+32],al
    inc bx
    loop s

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

問題2:
運行結果如下,相加成功

實驗任務4

代碼如下:

assume cs:code

data1 segment
    dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends 

data2 segment
    dw 8 dup(?)
data2 ends
stack segment
    db 16 dup(0)
stack ends
code segment
start:
    mov ax,data1
    mov ds,ax
    mov ax,stack
    mov ss,ax
    mov sp,16
    mov bx,0
    mov cx,8
s1:
    push ds:[bx]
    inc bx
    inc bx
    loop s1

    mov bx,16
    mov cx,8
s2:
    pop ds:[bx]
    inc bx
    inc bx
    loop s2

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

運行結果如下

分析:
使用棧先進后出的特性,完成逆序存放。因為棧每次放入一個字,數據也是一個字,非常完美的配合起來了。

實驗任務5

  • 問題1運行結果

  • 問題2測試結果(line 25 line 27之前)

  • 代碼line19的作用是將所有字母轉換為大寫字母
    0dfh轉換為二進制可得
    11011111
    大寫字母ASCII碼
    0100 0001 ~ 0101 1010
    小寫字母ASCII碼
    0110 0001 ~ 0111 1010
    可以觀察得出,相差的位數就是第三位(從高到低,從1開始數)。
    所以只需要將第三位置零,其他位保持不變即可。
    所以只需要與上11011111即可,因為任意位數與上00,任意數字與上1不變。

  • 問題4測試結果

    分析以及猜測:
    顯示一個字符占一個字,低位字節表示是什么字母(ASCII碼),第二個字節表示字符的顯示參數,高四位表示字符的底色,低四位表示字符得顏色。

實驗任務6

  • 程序源代碼

    assume cs:code, ds:data
    
    data segment
    db 'Pink Floyd      '
    db 'JOAN Baez       '
    db 'NEIL Young      '
    db 'Joan Lennon     '
    data ends
    
    code segment
    start:
    mov ax,data
    mov ds,ax
    mov cx,4
    mov bx,0
    s:  
    mov dx,cx
    mov cx,4
    mov si,0
        p:
            mov al,ds:[bx+si]
            or al,00100000B
            mov ds:[bx+si],al
            inc si
        loop p
    add bx,16
    mov cx,dx
    loop s
    
    mov ah, 4ch
    int 21h
    code ends
    end start
    
  • 運行結果

    分析:使用二重循環,dx用來暫存cx的值。此處也可以用棧來保存,但是由於只需要保存cx,所以可以暫時不用棧

實驗任務7

assume cs:code, ds:data, es:table

data segment
    db '1975', '1976', '1977', '1978', '1979' ;一個數字占4個字節,0起步,每次偏移量為4
    dw  16, 22, 382, 1356, 2390 ;一個數字占一個字,20起步,每次偏移2
    dw  3, 7, 9, 13, 28 ;一個數字占一個字,30起步,每次偏移2
data ends

table segment
    db 5 dup( 16 dup(' ') )  ;
table ends

code segment
start:
    mov ax,data
    mov ds,ax
    mov ax,table
    mov es,ax
    mov cx,5
    mov bx,0
    mov si,0
s:

    mov ax,[bx+2]
    mov es:[di+2],ax
    mov ax,[bx]
    mov es:[di],ax
    mov ax,[si+20]
    mov es:[di+5],0
    mov es:[di+7],ax
    mov ax,[si+30]
    mov es:[di+11],ax
    mov es:[di+9],0
    mov ax,es:[di+7]
    div byte ptr es:[di+11]
    mov byte ptr es:[di+13],0
    mov es:[di+14],al
    add bx,4
    add si,2
    add di,16
    loop s
    mov ah, 4ch
    int 21h
code ends
end start

程序運行截圖

原始數據截圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM