包含多个段的程序---汇编学习笔记
包含多個段的程序
要使用一段安全的空間,第五章中我們說0:200~0:2ff是相對安全的。可這段代碼容量只有256個字節。
合法地通過操作系統取得的空間都是安全的。
程序取得所需空間的方法有兩種,一是加載程序的時候程序分配,再就是程序在執行的過程中向系統申請。
對于使用多個段的問題,我們將討論:
(1)在一個段中存放數據、代碼、棧,我們先來體會一下不使用多個段時的情況;
(2)將數據、代碼、棧放入不同的段中。
6.1 在代碼段中使用數據
考慮這樣一個問題,編程計算以下8個數據的和,結果存在ax寄存器中:
0123h、0456h、0789h、0abch、0defh、0fedh、0cbah、0987h
我們如何去尋找這個內存段的空間呢?(這里有代碼段和數據段)
從規范的角度來講,我們不能自己隨便決定哪段空間可以使用,應該由系統來分配。我們可以在程序中,定義我們希望處理的數據,這些數據就會被編譯、連接程序作為程序的一部分寫到可執行文件中。當可執行文件中的程序被加載入內存時,這些數據也同時被加載入內存中。與此同時,我們要處理的數據也就自然而然地獲得了存儲空間。
看具體程序:
assume cs:code code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h ;dw代表是字型數據mov bx,0mov ax,0mov cx,8 s: add ax,cs:[bx]add bx,2loop smov ax,4c00hint 21hcode ends end編譯、連接這段程序后,我們看到如下:
顯然,我們程序從cs:ip開始,而cs開始部分就是數據部分。明顯是我們程序在代碼段的dw影響了這段代碼開始執行的位置(更準確的說,是我們沒有定義數據段)。
那么,我們怎樣讓程序正確的(或說cs:ip)指向程序入口呢?如下:
assume cs:code code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hstart: mov bx,0mov ax,0mov cx,8 s: add ax,cs:[bx]add bx,2loop smov ax,4c00hint 21hcode ends end start如上代碼所看到的,我們在兩處加了start。
可執行文件中的程序執行過程如下:
現在的問題是:我們由什么來判定程序入口呢?具體框架如下
6.2 在代碼段中使用棧
完成下面的程序,利用棧,將程序中定義的數據逆序存放。
assume cs:code code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h? mov ax,4c00hint 21hcode ends end程序思路:定義的數據存放在cs:0~f單元中,我們只要將數據依次入棧,再依次出棧就可以逆序存放了。
問題是:我們首先要有一段可當作棧的內存空間。如下:
assume cs:code code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;用dw定義16個字型數據,在程序加載后,將取得16個字的;內存空間,存放這16個數據。后面的程序段中將這段空間;當作棧來使用start: mov ax,csmov ss,axmov sp,30h ;將設置棧頂ss:sp指向cs:30mov bx,0mov cx,8s: push cs:[bx]add bx,2loop s ;將代碼段0~15單元中的8個字型數據依次入棧mov bx,0mov cx,8s0: pop cs:[bx]add bx,2loop s0mov ax,4c00hint 21hcode ends end start自此,我們的程序段定義并且使用了,發現很麻煩。
檢測點 6.1
(1)下面程序實現依次使用內存0:0~0:15單元中的內容改寫程序中的呃數據,完成程序:
assume cs:code code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hstart: mov ax,0mov ds,axmov bx,0mov cx,8 s: mov ax,[bx]mov cs:[bx],ax ;題目這段代碼為空,需要自己填寫add bx,2loop smov ax,4c00hint 21hcode ends end start(2)下面的程序實現依次內存0:0~0:15單元中的內容改寫程序中的數據,數據的傳送用棧來進行。棧空間設置在程序內。完成程序:
assume cs:code code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdw 0,0,0,0,0,0,0,0start: mov ax,cs ;題目ax后面為__mov ss,axmov sp,20h ;題目ss后面為__mov ax,0mov ds,axmov bx,0mov cx,8s: push [bx]pop cs:[bx] ;題目為________add bx,2loop smov ax,4c00hint 21hcode ends end start6.3 將數據、代碼、棧放入不同的段
在前面的內容中,我們在程序中用到了數據和棧,將數據、棧和代碼都放在了一個段里面。
這樣做顯然有兩個問題:
(1)把它們放在一個段中使程序顯得混亂
(2)前面程序中處理的數據很少,用到的棧空間也很小,加上沒有很長的代碼,放到一個段里面沒有問題。但如果數據、棧和代碼需要的空間超過64KB,就不能放在一個段中。
所以,應該考慮用多個段存放數據、棧和代碼。如下所示:
assume cs:code,ds:data,ss:stack;數據段 data segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h data ends;棧段 stack segmentdw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 stack ends;代碼段 code segmentstart: mov ax,stackmov ss,axmov sp,20h ;設置棧頂ss:sp指向stack:20mov ax,datamov ds,axmov bx,0 ;設置ds:bx指向data段的第一個單元mov cx,8 s: push [bx]add bx,2loop s ;以上將data段中的0~15單元中的8個字型數據一次入棧mov bx,0mov cx,8 s0: pop [bx]add bx,2loop s0 ;以上依次出棧8個字型數據到data段的0~15單元中mov ax,4c00hint 21hcode endsend start程序說明:
(1)定義多個段的方法
定義一個段的方法和前面所講的定義代碼段的方法沒有區別,只是對于不同的段,要有不同的段名。
(2)對段地址的引用
現在,程序中有多個段了,如何訪問段中的數據呢?當然要通過地址,而地址是分為兩部分,即段地址和偏移地址。如何指明要訪問的數據的段地址呢?在程序中,段名就相當于一個標號,它代表了段地址。(形如:mov ax,data)
(3)“代碼段”、“數據段”、“棧段”完全是我們的安排
–
實驗 5 編寫、調試具有多個段的程序
(1)將下面的程序編譯連接,用Debug加載、跟蹤,然后回答這個問題。
assume cs:code,ds:data,ss:stackdata segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h data endsstack segmentdw 0,0,0,0,0,0,0,0 stack endscode segment start: mov ax,stackmov ss,axmov sp,16mov ax,datamov ds,axpush ds:[0]push ds:[2]pop ds:[2]pop ds:[0]mov ax,4c00hint 21hcode ends end start1.CPU執行程序,程序返回前,data段的數據為多少?
2.CPU執行程序,程序返回前,cs=?、ss=?、ds=?。
3.設置程序加載后,code段的段地址為X,則data段的段地址為?,stack段的段地址為?。
code=X、data=X-20、stack=X-10。
(2)將下面的程序編譯連接,用Debug加載、跟蹤,然后回答問題。
assume cs:code,ds:data,ss:stackdata segmentdw 0123h,0456h data endsstack segmentdw 0,0 stack endscode segment start: mov ax,stackmov ss,axmov sp,16mov ax,datamov ds,axpush ds:[0]push ds:[2]pop ds:[2]pop ds:[0]mov ax,4c00hint 21hcode ends end start1.CPU執行程序,程序返回前,data段中的數據為多少?
2.CPU執行程序,程序返回前,cs=?、ss=?、ds=?。
3.設程序加載后,code段的段地址為X,則data段的段地址為?,stack段的段地址為?。
cs = X , ds = X-20, ss = X-10。
4.對于如下定義的段:
name segment
···
name ends
如果段中的數據占N個字節,則程序加載后,該段實際占有的空間為?。
N/256取上整
(3)將下面的程序編譯連接,用Debug加載、跟蹤,然后回答問題。
assume cs:code,ds:data,ss:stackcode segment start: mov ax,stackmov ss,axmov sp,16mov ax,datamov ds,axpush ds:[0]push ds:[2]pop ds:[2]pop ds:[2]mov ax,4c00hint 21hcode endsdata segmentdw 0123h,0456h data endsstack segmentdw 0,0 stack endsend start1.CPU執行程序,程序返回前,data段中的數據為多少?
2.CPU執行程序,程序返回前,cs=?、ss=?、ds=?。
3.設程序加載后,code段的段地址為X,則data段的段地址為?,stack的段地址為?。
code=X , data=X+(code指令字節數/256)取上整+1 , stack = data + 1。
(4)如果將(1)(2)(3)題中的最后一條偽指令“end start”改為“end”(也就是說,不指名程序的入口),則哪個程序仍然可以正確執行?請說明原因。
第3個可以,首先是指令從何處開始,3可以正確的指向指令開始出,而其他兩個不行;其次,是指令結束,3個都可以正常結束,因為只要遇到mov ax,4c00h和int 21h執行完后,程序就返回了。
(5)程序如下,編寫code段中的代碼,將a段和b段中的數據依次相加,將結果存到c段中。
assume cs:codea segmentdb 1,2,3,4,5,6,7,8 a endsb segmentdb 1,2,3,4,5,6,7,8 b endsc segmentdb 0,0,0,0,0,0,0,0 c ends ;題目code需要自己編寫 code segment start:mov ax,cmov ds,axmov bx,0mov ax,amov es,axmov cx,8s: mov dl,0add dl,es:[bx]add dl,es:[bx+16]mov [bx],dlinc bxloop smov ax,4c0hint 21hcode ends end start實驗結果如下:
(6)程序如下,編寫code段中的代碼,用push指令將a段中的前8個字型數據,逆序存儲到b段中。
實驗結果如下:
本章完
總結
以上是生活随笔為你收集整理的包含多个段的程序---汇编学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三步拆解一个数据分析体系
- 下一篇: 中国游戏行业观察报告