匯編--基礎分析:數據段在內存中的存放及空間


在學習王爽匯編第六章的時候,接觸到在源程序中不同段的設置,如數據段、棧段、代碼段的分別設置。

如下格式:

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

data segment
   ...
data ends

stack segment
   ...
stack ends

code segment

start:  
   ...

code ends

end start

那么對於data段定義的數據來說,定義后CPU給這段數據的空間大小是如何確定的呢?通過第六章的實驗題目,可以知道:數據段空間大小為定義數據所需的16字節的最小整數倍。比如定義了1個字節,系統就給數據段分配16個字節;定義了17個字節,系統就分配32個字節。
用一個簡單的示例程序加載,查看:

assume cs:code,ds:data
data segment
  db 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,10h,11h
data ends

code segment
start:
  mov bx,1
  mov ax,4c00h
  int 21h
code ends

end start

debug加載執行文件后,觀察(ds)=13d5h,則13d5:0~13d5:ff為PSP區域,則13d5:100為源程序入口地址。
則通過-d 13d5:100 10f查看入口開始后16個字節,發現16個字節與數據段定義的前16個數據一致。

繼續-d 13d5:100 11f查看入口開始的32個字節,發現17個字節與數據段定義的17個數據一致,並且后15個字節均為0.

那么我們可以得出一個結論:數據定義時候的17個字節被正確放入了內存,可是現在還不能驗證數據段占據的空間是32個字節。

因為緊跟在數據段后面的就是代碼段。

那么我們先用u命令查看代碼對應的機器指令,可以觀察到:代碼段的入口地址為13e7:0000;也就是說從加載時候的入口到代碼段入口之前的區域為data段區域,這段區域范圍為:13d5:100~13e6:f,即13e50~13e6f.通過(13e6f-13e50+1)計算出這段區域大小為20H,即32個字節。

接下來還有一個疑問,如果定義時候數據段如下定義,那它在內存中如何排布和分配空間呢?

assume cs:code,ds:data
data segment
  db 1,2,3
  db 4,5
data ends

code segment
start:
  mov bx,1
  mov ax,4c00h
  int 21h
code ends

end start

通過兩次db定義,對上例來說,是分別分配兩個16字節的空間分別存放兩個db定義的數據,還是作為一個整體考慮呢?
通過debug加載后查看內存,可以觀察到定義時候雖然分成了兩個db去定義,但內存中這5個數據是連續的,作為一個整體考慮。

ds在加載初始為13d5,即源程序入口地址為:13d50+100=13e50h;通過u命令,代碼入口地址為13e60h;兩者相減得到數據段空間為16個字節。

這里仍然要說明的一點是:

當程序加載到內存中的時候,DS寄存器存放的是整個程序包含其與系統的通訊信息(PSP)所占區域的段地址。即ds:0為整個程序和信息區的起始地址,PSP區占據開始的256個字節,即ds:0~ff為PSP區域。從ds:100開始才真正為源程序指令的入口地址。如本文上例,ds:100就為data段的段地址。並且,data標識符就注明了這一段地址,我們知道同一內存地址的段地址可以有多種設置,對這里而言,data標識符匹配的段地址是:“當偏移地址為0"時的段地址,所以data從數值上等於(ds+10h).而程序開頭的assume只是偽指令,是提供給編譯器的說明信息,並不會被轉化為機器指令執行。所以當我們需要使用data段的數據時候,需要通過如下的指令設置:

...
   mov ax,data
   mov ds,ax
...

同樣的,code標識符匹配的也為偏移地址為0情況下的段地址,因為cs直接就設置為該段地址,所以這里不需要通過代碼特殊設置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM