1. 程式人生 > 實用技巧 >CSP-S 2020 遊記

CSP-S 2020 遊記

一、實驗目的

1.理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯 2.理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式 3.掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法
4.理解並掌握各種定址方式的靈活應用
5.掌握彙編指令loop, and, or,div, mul的用法

二、實驗準備

複習教材chapter 6-8章。
  • chapter 6包含多個段的程式
  • chapter 7更靈活的定位記憶體地址的方法
  • chapter 8資料處理的兩個基本問題

三、實驗內容

1.實驗任務1

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

 1 assume cs:code, ds:data
 2 data segment
 3         db 'Nuist'
 4         db 5 dup(2)
 5 data ends
 6 
 7
code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 12 mov ax, 0b800H 13 mov es, ax 14 15 mov cx, 5 16 mov si, 0 17 mov di, 0f00h 18 s: mov al, [si] 19 and al, 0dfh 20 mov es:[di], al 21 mov al, [5+si] 22 mov es:
[di+1], al 23 inc si 24 add di, 2 25 loop s 26 27 mov ah, 4ch 28 int 21h 29 code ends 30 end start

閱讀源程式,從理論上分析原始碼的功能,尤其是line15-25,迴圈實現的功能是什麼,逐行理解每條指令的功能。

  • 使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task1.exe,執行並觀察結果。
  • 使用debug工具對程式進行除錯,執行到程式返回前,即line27之前,觀察結果。
  • 修改line4裡5個位元組單元的值,重新彙編、連結、執行,觀察結果。
1 db 5 dup(2) 
2 --> 改成:
3 db 2,3,4,5,6

基於觀察,分析、猜測這裡的數值作用是什麼。

2.實驗任務2

已知資料段data中定義位元組資料如下:

1 data segments
2     db 23, 50, 66, 71, 35
3 data ends

編寫程式,在螢幕上以十進位制整數形式列印輸出這5個兩位數。

提示:

  • 1個兩位數如何輸出
    思路如下:


    具體處理步驟如下:
    第1步,利用除法指令div,計算出每個數位上的數值。
    第2步,利用數值和數字字元之間ascII碼的關係,把數值→數字字元
    第3步,利用系統功能呼叫int 21h中的2號子功能,輸出單個字元。

    int 21h中的2號子功能說明如下:
    功能:輸出單個字元
    用法:
    1 mov ah, 2
    2 mov dl, ×× ; ××是待輸出的字元,或其ASCII碼值 
    3 int 21h
  • 5個兩位數如何輸出
    利用loop指令,以及,靈活的定址方式。

3.實驗任務3

教材「實驗5編寫、除錯具有多個段的程式」(1)

程式原始碼見task3.asm。

4.實驗任務4

教材「實驗5編寫、除錯具有多個段的程式」(2)

程式原始碼見task4.asm。

5.實驗任務5

教材「實驗5編寫、除錯具有多個段的程式」(3)

程式原始碼見task5.asm。

6.實驗任務6

教材「實驗5編寫、除錯具有多個段的程式」(4)

7.實驗任務7

教材「實驗5編寫、除錯具有多個段的程式」(5)

程式原始碼見task7.asm。

注*:如果在整合軟體環境下編寫、彙編這個實驗任務,請將段名為c的邏輯段,名稱改為c1或別的標識 符。由於早期一些指令集中使用c指代暫存器,如不更正,有些彙編器在彙編時會報錯。

1 c segment ; 段名稱改成c1或別的合法的識別符號
2  ...
3 c ends ; c1

8.實驗任務8

教材「實驗5編寫、除錯具有多個段的程式」(6)

程式原始碼見task8.asm。

四、實驗結論

1.實驗任務1

task1:

 1 assume cs:code, ds:data
 2 data segment
 3         db 'Nuist'
 4         db 5 dup(2)
 5 data ends
 6 
 7 code segment
 8 start:
 9         mov ax, data
10         mov ds, ax
11 
12         mov ax, 0b800H
13         mov es, ax
14 
15         mov cx, 5
16         mov si, 0
17         mov di, 0f00h
18 s:      mov al, [si]
19         and al, 0dfh
20         mov es:[di], al
21         mov al, [5+si]
22         mov es:[di+1], al
23         inc si
24         add di, 2
25         loop s
26 
27         mov ah, 4ch
28         int 21h
29 code ends
30 end start

程式碼的line15-25是實現了將data segment中存放的字母全部變為大寫,並賦上顏色輸出到視訊記憶體。其中line15記錄了迴圈的次數,line16記錄了ds的起始偏置,line17記錄了視訊記憶體的起始偏置。

從line18開始進入到迴圈,line18其實是mov al, ds:[si],將data segment中的第一個字元“N”傳入到al暫存器中,在line19將al與DFH做與運算,將其轉換為大寫字母,在line20將該大寫字母寫入視訊記憶體,line21和line22實現將顏色資訊傳入到視訊記憶體中。

使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task1.exe,執行並觀察結果。

使用debug工具對程式進行除錯,執行到程式返回前,即line27之前,觀察結果。

修改line4裡5個位元組單元的值,重新彙編、連結、執行,觀察結果。

1 db 5 dup(2)
2  --> 改成:
3 db 2,3,4,5,6

猜想,視訊記憶體字資料中高位位元組裡存放的是顏色資訊,低位位元組裡存放的是內容資訊。IA32採用的是小端存放,所以先存放的是低位內容資訊,後存放的是高位顏色資訊。內容資訊是ASCII碼,顏色資訊是8位顏色資訊。所以line4存放的是顏色資訊。

2.實驗任務2

 1 assume cs:code, ds:data
 2 data segment
 3     db 23, 50, 66, 71, 35
 4 data ends
 5 
 6 code segment
 7 start:
 8     mov ax, data
 9     mov ds, ax
10 
11     mov cx, 5
12     mov si, 0
13 
14 s1: mov bl, 10
15     mov ah, 0
16     mov al, [si]
17     div bl
18     mov bx, ax ;al存放的是商,ah存放的是餘數
19 
20     mov ah, 2
21     mov dl, 30h
22     add dl, bl
23     int 21h
24 
25     mov dl, 30h
26     add dl, bh
27     int 21h
28     mov dl," "
29     int 21h
30 
31     inc si
32     loop s1
33 
34     mov ah, 4ch
35     int 21h
36 code ends
37 end start

3.實驗任務3

(1)可以發現數據段內容沒有發生變化。
(2)在程式返回前,cs=076C,ss=076B,ds=076A (3)設程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。

4.實驗任務4

(1)data段資料未發生變化,0123H,0456H

(2)在程式返回前,cs=076C,ss=076B,ds=076A

(3)設程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。

(4)對於如下定義的段:

1 name segment
2  ...
3 name ends

如果段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為 16×⌈N/16⌉ 位元組。

5.實驗任務5

(1)CPU執行程式,程式返回前,data段中的資料為 0123H,0456H

(2)CPU執行程式,程式返回前,cs=076AH,ss=076EH,ds=076DH。

(3)設程式載入後,code段的段地址為X,則data段的段地址為X+3,stack段的段地址為X+4。

6.實驗任務6

如果將(1)、(2)、(3)題中的最後一條偽指令“end start”改為“end”(也就是說,不指明程式的入口),則哪個程式仍然可以執行?請說明原因。

答:第(3)題的程式task5.exe仍然可以正確執行,因為如果不指明入口位置,程式就會預設以ip=0執行,而不是從start開始執行,而(3)的data和stack都在code之後,所以ip本來就為0,可以正確執行。

7.實驗任務7

 1 assume cs:code
 2 a segment
 3   db 1,2,3,4,5,6,7,8
 4 a ends
 5 
 6 b segment
 7   db 1,2,3,4,5,6,7,8
 8 b ends
 9 
10 c1 segment   ; 在整合軟體環境中,請將此處的段名稱由c→改為c1或其它名稱
11   db 8 dup(0)
12 c1 ends
13 
14 code segment
15 start:
16     mov ax, a
17     mov ds, ax
18     mov cx,8
19     mov si,0
20 
21 s:  mov ax,[si]
22     add ax,[si+10H]
23     mov [si+20H],ax
24     inc si
25     loop s
26     
27     mov ax,4c00H
28     int 21H
29 code ends
30 end start

8.實驗任務8

 1 assume cs:code
 2 a segment
 3   dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
 4 a ends
 5 
 6 b segment
 7   dw 8 dup(0)
 8 b ends
 9 
10 code segment
11 start: 
12     mov ax,a
13     mov ds,ax
14     mov ax,b
15     mov ss,ax
16     mov si,0
17     mov cx,8
18     mov sp,10H
19     
20 s:  push [si]
21     add si,2
22     loop s
23 
24     mov ax,4c00h
25     int 21h
26 code ends
27 end start