1. 程式人生 > 實用技巧 >activity 帶資料跳轉

activity 帶資料跳轉

一、實驗目的 1. 理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯 2. 理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式 3. 掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法 4. 理解並掌握各種定址方式的靈活應用 5. 掌握彙編指令loop, and, or,div, mul的用法 二、實驗內容 1.實驗任務1
assume cs:code, ds:data
data segment
        db 'Nuist'
        db 5 dup(2)
data ends

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

        mov ax, 0b800H
        mov es, ax

        mov cx, 5
        mov si, 0
        mov di, 0f00h
s:      mov al, [si]
        and al, 0dfh
        mov es:[di], al
        mov al, [5+si]
        mov es:[di+1], al
        inc si
        add di, 2
        loop s

        mov ah, 4ch
        int 21h
code ends
end start
進行編譯連線: 執行task:

進行debug,使用r命令觀察接著根據CX進行反彙編

發現反彙編的結果並不是完全正確,多了很多冗餘資料,使用g命令執行到程式結束之前:

進行修改:

重新進行編譯連線:

發現NUIST的IST顏色變色了,所以我猜測這裡的資料作用是改變字串的顏色資訊

2.實驗任務2

已知資料段data中定義位元組資料如下: data segments db 23, 50, 66, 71, 35 data ends 編寫程式,在螢幕上以十進位制整數形式列印輸出這5個兩位數。 先把ds指向資料段,定好迴圈次數cx為5次 定義迴圈s:因為資料段中的每個十位數僅有8個字型資料,所以用al來儲存 接著使用div除法命令,商存入al,而餘數存在ah中 接著將ax複製到dx中並且加上3030H使得數字轉化成數字字元 根據老師所給的int 21h的2號子功能,最後輸出的是dl中的內容 所以先直接輸出一次接著將dh複製到dl中在輸出一次即為一個十進位制數的輸出過程 一次迴圈結束,將ds指向向後移一位,開始下一次迴圈直到五次結束。 程式碼如下:
assume cs:code,ds:data
data segment
        db 23,50,66,71,35
data ends

code segment
start:
        mov ax,data
        mov ds,ax
        mov cx,5
s:      mov ah,0
        mov al,ds:[di]
        mov bl,10
        div bl
        mov dx,ax
        add dx,3030H
        mov ah,2
        int 21h
        mov dl,dh
        mov ah,2
        int 21h
        inc di
        loop s
        mov ah,4CH
        int 21h
code ends
end start

進行編譯連線並執行:

得到了輸出結果23,50,66,71和35

3.實驗任務3

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
data ends

stack segment
  dw 0, 0, 0, 0, 0, 0, 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

教材問題1:CPU執行程式,程式返回前,data段中的資料為多少?

理論分析來說,不會發生變化

原來data段中存放的資料:到程式返回前,data段中存放的資料為:

執行到程式結束前的資料段:

問題2:CPU執行程式,程式返回前,cs=,ss=,ds=

根據問題1的第二張圖片可得:cs=076C,ss=076B,ds=076A

問題3:設程式載入後,code段的段地址為X,則data段的段地址為,stack段的段地址為

data段的段地址為X-2,stack段的段地址為X-1,因為程式開始前data定義了16個位元組空間的資料,stack定義了16個位元組空間的資料,所以每一個段相差16個即10h個位元組。

4. 實驗任務4
assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

1.CPU執行程式,程式返回前,data段中的資料為多少?

進入程式進行反彙編到程式返回前

檢視資料段中的值

由程式得,data段中的資料應為4個位元組的內容即0123h,0456h

2.CPU執行程式,程式返回前,cs=,ss=,ds=?

由上圖得,cs=076C,ss=076B,ds=076A

3.設程式載入後,code段的段地址為X,則data段的段地址為,stack段的段地址為

data:X-2,stack:X-1

4.首先佔用的位元組數最少為16個且一定為16的倍數,如果N可以整除16,那麼

佔有的空間就為N個位元組,如果不可以,實際佔有的空間為(N/16+1)*16

5.實驗任務5

assume cs:code, ds:data, ss:stack

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0,0
stack ends
end start

1.CPU執行程式,程式返回前,data段中的資料為多少?

data段仍舊佔4個位元組,為0123h,0456h

2.CPU執行程式,程式返回前,由執行結果可以看出cs=076A,ss=076E,ds=076D

3.設程式載入後,code段的段地址為X,則data段的段地址為,stack段的段地址為

data段的段地址為X+3,stack段的段地址為X+4

6.實驗任務6

如果將實驗任務3,4,5中的最後一條偽指令“end start”改為“end”(也就是說,不指明程式的入口),則哪個程式仍然可以正確執行?請說明原因

解:只有實驗任務5的程式還可以正確執行,因為實驗任務5的程式的資料段和棧段都定義在程式的code段後,u命令反彙編的情況下不會影響,而實驗任務3,4都定義在code段前,前面定義的data段和棧段中的資料會當作程式碼進行反彙編,無法正確執行。

7.實驗任務7

編寫code段中的程式碼,將a段和b段中的資料依次相加,將結果儲存到c段中

assume cs:code
a segment
  db 1,2,3,4,5,6,7,8
a ends

b segment
  db 1,2,3,4,5,6,7,8
b ends

c1 segment   ; 在整合軟體環境中,請將此處的段名稱由c→改為c1或其它名稱
  db 8 dup(0)
c1 ends

code segment
start:
       mov di,0
       mov cx,8
s:     mov si,a
       mov ds,si
       mov al,ds:[di]
       mov si,b
       mov ds,si
       add al,ds:[di]
       mov si,c1
       mov ds,si
       mov ds:[di],al
       inc di
       loop s
       mov ax,4c00h
       int 21h
code ends
end start

執行到程式結束前,用d命令檢視現在DS存放的內容

發現結果為02 04 06 08 0A 0C 0E 10,完成了要求

8.實驗任務8

編寫code段中的程式碼,用push指令將a段中的前8個字型資料,逆序儲存到b段中

assume cs:code
a segment
  dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends

b segment
  dw 8 dup(0)
b ends

code segment
start: 
      mov di,0
      mov cx,8
s:    mov si,a
      mov ds,si
      push ds:[di]
      inc di
      inc di
      loop s
      mov di,0
      mov cx,8
s1:   mov si,b
      mov ds,si
      pop ds:[di]
      inc di
      inc di
      loop s1
      mov ax,4c00h
      int 21h
code ends
end start

一開始想著逆序輸出到b段中就在第二個迴圈中將bi的初始值設成16,然後dec兩次,

嘗試了幾次發現還是正序,才想到棧的pop函式本身就是先入後出的逆序過程,

我相當於逆序的逆序還是正序了,接著直接進行同樣的步驟執行得到了結果

三、實驗總結

總體來說這次的實驗讓我很清晰的理解了段的分配機制,data段和棧段,定義段的位置

都會對結果產生莫大的影響,最後一個實驗任務還讓我對棧的知識回顧了一下,實驗任務2

讓我重新看了書本上div指令的部分,商預設儲存在al中,ah預設儲存餘數,int 21h的二號子命令

是輸出dl中的內容