C語言中處理結構體的原理
彙編中有幾種定址方式,分別是直接定址:(ds:[idata])、暫存器間接定址(ds:[bx])、暫存器相對定址(ds:[bx + idata]、ds:[bx + si])基址變址定址(ds:[bx + si])、相對基址變址定址([bx + si + idata])。
結構體的儲存邏輯圖如下:(以下資料表示某公司的名稱、CEO、CEO的福布斯排行、收入、代表產品)
現在假設公司的CEO在富豪榜上的排名為38,收入增加了70,代表產品變為VAX,通過彙編程式設計修改上述資訊,以下是相應的彙編程式碼:(假設資料段為seg)
mov ax,seg
mov ds,ax
mov bx,0
mov word ptr ds:[bx + 12],38
add [bx + 14],70
mov si,0
mov byte ptr [bx + 10 + si],'V'
inc si
mov byte ptr [bx + 10 + si],'A'
inc si
mov byte ptr [bx + 10 + si],'X'
對應的C語言程式碼可以寫成:
struct company
{
char cn[3];
char name[9];
int pm;
int salary;
char product[3];
};
company dec = {"DEC" ,"Ken Olsen",137,40,"PDP"};
int main()
{
int i;
dec.pm = 38;
dec.salary += 70;
dec.product[i] = 'V';
++i;
dec.product[i] = 'A';
++i;
dec.product[i] = 'X';
return 0;
}
對比C語言程式碼和彙編程式碼,可以看出,對於結構體變數,系統會先根據定義分配相應大小的空間,並將各個變數名與記憶體關聯起來,結構體物件名與系統分配的空間的首地址相對應(定義的結構體物件的首地址在段中的相對地址儲存在bx中),即在使用dec名時實際與彙編程式碼“mov ax,seg” “mov ds,ax”
對應,將資料段段首地址存入ds暫存器中,系統根據物件中的變數名找到對應的偏移地址,偏移地址的大小由對應的資料型別決定,如cn陣列前沒有變數,cn的偏移地址為0,cn所在的地址為 ds:[bx],cn為長度為3的字元型陣列,在上一個偏移地址的基礎上加上上一個變數所佔空間的大小即為下一個變數的偏移地址,所以name陣列的首地址為ds:[bx + 3],這樣給出了物件名就相當於給定了該物件在段中的相對地址(上述程式碼中的bx),給定了物件中的成員變數名就相當於給定了某一記憶體在物件中的偏移地址(ds:[bx + idata])。根據陣列名可以找到陣列的首地址,但陣列中具體元素的訪問則需要給定元素個數,即si的值來定位陣列中的具體記憶體,C語言中的 ++i 相當於彙編中的 (add si ,陣列中元素的長度)。
根據以上的分析可以看出,構建一個結構體物件時,系統會在程式碼段中根據結構體的定義開闢相應大小的記憶體空間,並將該空間在段中的偏移地址與物件名繫結。物件中的變數名與該變數在物件所在記憶體中的偏移地址相關聯,陣列中的標號用於定位陣列中的元素在陣列中的相對位置。(物件名決定bx,變數名決定bx + idata,陣列中的元素標號決定bx + idata + si)。