《組合語言》學習(六)多個段的程式

2021-07-23 14:51:51 字數 4681 閱讀 4561

《組合語言》第六章主要講述「如何編寫包含多個段的彙編源程式」。本章的文字內容不多,主要通過程式設計實踐來理解彙編源程式架構的含義,通篇學下來,我覺得有以下幾點需要理解清楚:

1,這裡所說的多個段(segment),從彙編「程式」的角度來說,它指的是程式所占用的記憶體空間的劃分,大致分為:data segment、stack segment和code segment。其實際就是指定執行時cpu的ds、ss和cs這三個暫存器的值。

2,但是,從源程式的角度來看,它指的是**的組織方式。源程式分成多個段,是的**的層次更清晰。

3,我們通常講的多個段,更多的還是從源程式的角度來說的。事實上,乙個段的源程式,通過設定cpu的暫存器也可以劃分程式的記憶體空間。

4,組合語言通過在源程式中使用段名(name)來標記各個段。

5,源程式中的段名(name)和標號(label),它們本質上都代表乙個位址。在debug下反彙編,我們可以看到,段名和標號都被它們**的位址值替代了。

6,不同的是,段名代表的是段位址(sa),標號代表的是偏移位址(ea)。

7,源程式通過「end+label」指定入口位址(entry),當然,這個入口位址僅僅是偏移位址。預設為0。

8,這個入口位址的資訊被記錄在.exe的描述資訊中,對應「psp(程式段字首)」。

9,程式載入的時候,cs由系統指定(或者說由引導程式指定,shell);引導程式會搜尋psp,根據其中的entry,設定ip的值,預設為0。

10,嚴格來說,單段的程式只需要根據entry修改ip的值,多段的程式,則需要修改cs的值,cs的值按16位對齊,ip的值為0。

11,ip的值為16位,範圍為0-255,它能開闢的空間有限,故單段的程式不適合需要大記憶體的應用。而cs表示段位址,它的變化範圍就比較廣了,可以開大得多的記憶體空間。

本章的重點在於程式設計實踐,下面我將介紹我的程式設計實踐。

檢測點6.1

程式補全

(1)記憶體複製

assume cs:codesg

codesg segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

start:mov ax,0

mov ds,ax

mov bx,0

mov cx,8

s:mov ax,[bx]

mov cs:[bx],ax

add bx,2

loop s

mov ax,4c00h

int 21h

codesg ends

end start

(2)使用棧進行記憶體複製

assume cs:codesg

codesg segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

dw 0,0,0,0,0,0,0,0,0,0

start:mov ax,cs

mov ss,ax

mov sp,36

mov ax,0

mov ds,ax

mov bx,0

mov cx,8

s:push [bx]

pop cs:[bx]

add bx,2

loop s

mov ax,4c00h

int 21h

codesg ends

end start

以上兩個程式都是單段程式,這個不是主流,我就不詳細講解了。

實驗51,程式除錯

問題回答:

1)cpu執行程式,程式返回前,data段中的資料不變;

2)cs=

3)設程式載入後,code段的段位址為x,則data段的段位址為x-16 ,stack段的段位址為x-32

如上圖,重點觀察程式執行前後,ds、ss、cs和ip這幾個暫存器的值。分析如下:

1)程式載入後,執行前,ds=0cd7h,ss=0ce7h,cs=0ce9h,ip=0000h

根據第4章的知識可知,ds:0指向程式記憶體空間起始位址,或psp首位址,而psp為256byte,故ss初始化時為0ce7h,即ss:0 - ds:0 = 256。本來cs的值也應該是0ce7h,但是該程式的原始碼中用「end+start」改變了入口位址。如果是在單段的程式,僅修改ip的值,但是這是乙個多段的程式,直接修改了cs的值。

cs:0 - ss:0 = 20h。這個20h剛好是data segment和stack segment所佔的空間大小。

需要注意的是:cs的值會保持16位對齊。也就是說,我們在原始碼中,刪除幾個(小於16)data segment或stack segment中的元素,重新編譯、鏈結和載入後,在debug下檢視,cs的值還是0ce9。至於那段空間,會自動補0,進行填充。

2)程式執行後,ds=0ce7,ss=0ce8,cs=0ce9

ds和ss的值的變化實際上是程式執行的結果,即是程式設計師自己編寫指令修改它們的。

2,程式除錯

這道程式除錯題,與上一道相似,它的重點在問題4。實際上,它要表達的意思是:data segment、stack segment和code segment的段位址會按16位對齊。

如果乙個段中的資料佔n個位元組,則程式載入後,該段實際占有的空間為「ceil(n/16) * 16」。

3,程式除錯

如上圖,重點觀察程式執行前後,ds、ss、cs這幾個暫存器的值。分析如下:

1)程式載入後,執行前,ds=0cd2h,ss=0ce6h,cs=0ce2h

根據第4章的知識可知,ds:0指向程式記憶體空間起始位址,或psp首位址,而psp為256byte,故cs初始化時為0ce7h,即cs:0 - ds:0 = 256。

這個程式編譯後,cs段提到了第一位。

2)程式執行後,ds=0ce5,ss=0ce6,cs=0ce2

ds和ss的值的變化實際上是程式執行的結果,即是程式設計師自己編寫指令修改它們的。

這道題的目的是要說明,在編譯器看來,段名僅僅只是一種標記,誰排在前誰排在後,由原始碼的位置決定(編譯先後不同)。

3)該程式,即使將「end start」改變為「end」,也不影響編譯結果。

5,程式設計題(求和)

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

c segment

db 0,0,0,0,0,0,0,0

c ends

code segment

start:mov bx,0

mov cx,8

s:mov ax,a

mov ds,ax

mov dx,[bx]

mov ax,b

mov ds,ax

add dx,[bx]

mov ax,c

mov ds,ax

mov [bx],dx

inc bx

loop s

mov ax,4c00h

int 21h

code ends

end start

6,程式設計題(逆序複製)

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 0,0,0,0,0,0,0,0

b ends

code segment

start:mov ax,a

mov ds,ax

mov ax,b

mov ss,ax

mov sp,10h

mov bx,0

mov cx,8

s:mov ax,[bx]

push ax

add bx,2

loop s

mov ax,4c00h

int 21h

code ends

end start

組合語言學習筆記(六)包含多個段的程式

6.1在 段中使用資料 dw 定義字型資料 define word db 定義位元組資料 define byte assume cs codesg code segment dw 0123h,0456h 偏移位址從0 2 4 6.start mov bx,0 mov ax,0 mov cx,8 s ...

組合語言 多個段的程式

下面 展示了多段程式,功能是將data中的資料,翻轉儲存 assume cs code,ds data,ss stack data segment dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h data ends stack segment d...

組合語言學習筆記 六

1.前面講到要使用一段安全的空間0 200 0 300,可這段空間的容量只有256個位元組,如果我們需要的空間超過256個位元組該怎麼辦呢?將資料 棧放入不同的段中。2.dw 的含義是定義字型資料。dw即define word。db 的含義是定義位元組型資料。dw即define byte。3.end...