1. 程式人生 > 實用技巧 >集合運算在資料庫中的應用

集合運算在資料庫中的應用

一、實驗目的

1. 理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯

2. 理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式

3. 掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法

4. 理解並掌握各種定址方式的靈活應用 5. 掌握彙編指令loop, and, or,div, mul的用法

二、實驗準備

複習教材chapter 6-8章。

chapter 6 包含多個段的程式

chapter 7 更靈活的定位記憶體地址的方法

chapter 8 資料處理的兩個基本問題

三.實驗內容

實驗任務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

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

解:首先分析程式,第一步先初始化di,si,然後設定cx值為5,進行5次迴圈,然後將五個字母轉化成大寫後寫入視訊記憶體,然後利用高位字元控制在視訊記憶體輸出字元的顏色,然後再在視訊記憶體輸出低位字元NUIST,這裡的and做的是轉化字元為大寫,數字段中的5個2則是將字元顏色變為綠色。

然後進行編譯,連結,執行得到結果如下:

執行:

然後修改 dp 5 dup(2)為dp 2,3,4,5,6,結果如下:

從此實驗中可以看出,高位字元代表視訊記憶體低位輸出字元的顏色。

實驗任務2:

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

data segments
    db 23, 50, 66, 71, 35
data ends

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

編寫程式碼如下:

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 di,0
        mov cx,5
  
s:      mov ah,0
        mov al,ds:[di]
        mov bl,10
        div bl
        mov ds:[di+10],al
        mov ds:[di+11],ah
        
        mov ah,2
        mov dl, ds:[di+10]  
        add dl,30h
        int 21h
   
        mov ah,2
        mov dl, ds:[di+11]  
        add dl,30h
        int 21h
  
        mov ah,2
        mov dl, " " 
        int 21h
        inc di
        loop s
       
        mov ah, 4ch
        int 21h
code ends
end start

  經過編譯,連結,執行得到如下結果:

實驗任務3:

將下面的程式編譯、連結、用debug載入、跟蹤,然後回答問題:

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

經過編譯,連結

使用debug檢視:

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

資料可以看到為 0123 0456 0789 0ABC 0DEF 0FED 0CBA 0987

2.CPU執行程式,程式返回前,cs=076C ss=076B ds=076A

3.已知code地址段段地址為X,那麼data段段地址為?stack段段地址為?

data段段地址為X-2,stack段段地址為X-1

實驗任務4:

將下面的程式編譯、連結、用debug載入、跟蹤,然後回答問題:

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段中的資料為多少?

資料可以看到為 0123 0456

2.CPU執行程式,程式返回前,cs=076C ss=076B ds=076A

3.已知code地址段段地址為X,那麼data段段地址為?stack段段地址為?

data段段地址為X-2,stack段段地址為X-1

4.對於如下定義的段

name segment
...
name ends

如果段中的資料佔N個位元組,那麼程式載入後,該段實際佔有空間為:

可以綜合實驗3和實驗4,得到佔用空間為 (int(N/16)+1)*16

實驗任務5:

將下面的程式編譯、連結、用debug載入、跟蹤,然後回答問題:

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

  編譯,連結,執行:

然後debug:

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

資料可以看到為 0123 0456

2.CPU執行程式,程式返回前,cs=076A ss=076E ds=076D

3.已知code地址段段地址為X,那麼data段段地址為?stack段段地址為?

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

實驗任務6:

將前面那幾題中的最後一條偽指令”end start“改為”end“,哪個程式可以正確執行?

第三個,因為程式碼段定義在資料段和棧段之前,如果要反彙編資料段和棧段,也可以正確執行程式碼,不會改變程式開始的位置,所以可以正常的結束程式,另外兩個都在程式碼段之前,所以需要先反彙編,那麼就一定會改變程式碼段起始位置,無法執行。

實驗任務7:

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

程式碼如下:

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 bx,0
       mov cx,8
      
s:     mov si,a
       mov ds,si
       mov al,ds:[bx]

       mov si,b
       mov ds,si
       add al,ds:[bx]

       mov si,c1
       mov ds,si
       mov ds:[bx],al

       inc bx
       loop s
       mov ax,4c00h
       int 21h
       
code ends
end start

編譯,連結,debug如下:

可以看到C段結果如下:

實驗任務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 bx,0
mov cx,8
mov si,a
mov ds,si
s: push ds:[bx]
add bx,2
loop s
mov bx,0
mov si,b
mov cx,8
mov ds,si
c: pop ds:[bx]
add bx,2
loop c
mov ah,4ch
int 21h
code ends
end start

debug:

因為是dw雙位元組資料,所以每次bx要加2,可以看到1--8共8個數都已經全部逆序輸入到b段中。

四.實驗總結

在本次實驗中,我瞭解了記憶體中段的具體含義,段地址就代表了記憶體中某段地址用於儲存資料,同時需要弄清楚段中資料的具體所佔空間大小,同時要注意的是資料段的儲存,弄清楚資料儲存中的位元組大小,至少佔用16個位元組,同時避免程式碼執行混亂,一定要加上end start,否則容易混淆,導致程式碼無法正確執行。此外,還有使用div除法時,需要注意ah儲存商,al儲存餘數,同時在寫程式碼時要注意迴圈的位置,同時要注意使用bx和數字段b的時候不要混淆,會導致程式碼異常中斷。