在學習王爽匯編第六章的時候,接觸到在源程序中不同段的設置,如數據段、棧段、代碼段的分別設置。
如下格式:
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直接就設置為該段地址,所以這里不需要通過代碼特殊設置。