今天研究出了一個小問題,在C語言裏引用匯編的變量,會是什麼結果,彙編中的變量沒有像C語言中int類型那樣的類型約束,可以把數據當作任何類型處理,那麼傳到C語言中我們應該當作什麼類型處理呢。
換句話說,在彙編裏定義變量var,在C語言裏引用,我們肯定要用extern聲明var外部變量,那麼extern後面接什麼類型?難道是extern int var麼?還是 extern short var
實例:
注意:混合編譯的方法,gcc test.s main.c 這樣直接用gcc處理彙編和C語言文件就可以自動搞定。
一、
彙編程序:(是的,就這麼短小)
.global var #注意現在的彙編器不再要求被C語言引用的變量名前加下劃線 .data var: .fill 10,4,9 #填充10個單元,每個單元4字節,每個單元的值爲9
C語言:
#include <stdio.h> extern int var; //現在的C語言編譯器引用匯編變量可以使用和彙編變量同樣的名字,寫成_var反而會錯誤 void main() { printf("sizeof(var)=%d\n",sizeof(var)); printf("%d\n", var); }
程序的輸出爲
sizeof(int)=4 9
解釋很簡單,
如上圖,我只畫了四個字節,我填充了10個單元的,每單元佔用4字節,意思就是每個9佔四個字節。如圖,然後C語言裏聲明爲extern int var;就是把前四個字節看作一個int變量取出來,當然是9了。
二、
保持C語言程序和上一個一樣,
extern int var;
把彙編語句改成
.fill 10,2,9 #10個單元,每個單元填入9,每單元大小爲2B
這就意味着每個單元2字節,每個單元填一個9,我們不改變C語言語句,那麼仍將把var看作int型4字節變量,依然是一次取出前4個字節作爲var的值。那我們推測一下結果會是什麼。
首先每個9佔用兩字節,內存圖應該是這樣的,(只畫了4字節,後面沒畫)
一次性取出4個字節,就是0x00090009,這玩意兒拿到windows自帶計算器裏算出來是是十進制的589833,這就是我們的預測值。讓我們看下程序結果是不是和我們猜的一樣。
沒錯吧,這就是說我們在彙編裏定義的變量,來到C語言裏可以任意聲明爲任意類型,從sizeof的輸出也能看出,我們把var聲明成多大,它就是多大。
三、
我們再試試別的,彙編語句保持和上一個一樣,依然是
.fill 10,2,9 #10個單元,每個單元填入9,每單元大小爲2B
我們改變C語言語句,把var聲明成
extern long long var; //8字節整型
當然,輸出語句稍微變下,因爲是long long型整數,所以要這麼輸出printf("%lld\n", var);
#include <stdio.h> extern long long var; void main() { printf("sizeof(var)=%d\n",sizeof(var)); printf("%lld\n", var); }
我們還是事先猜測結果,字節太多我不畫圖了,按照上面的的思路,這次取出8字節當作long long變量var的值,那麼應該是0x0009000900090009,化爲十進制是2533313445691401。
看看程序運行結果:
預測正確。
四、
再來,把var聲明爲char變量。
#include <stdio.h> extern char var; #聲明爲char void main() { printf("sizeof(var)=%d\n",sizeof(var)); printf("%c\n", var); }
輸出語句相應的改變成%c
彙編裏面稍微改改填充的數值,因爲9是製表符的ASCII碼,輸出了你也看不到。我們改成填充43
.fill 10,2,43 #10個單元,每個單元填入43(內存實際存儲按照二進制來的),每單元大小爲2B
注意43的十六進制表示爲0x2b,這是加號“+”的ASCII碼,
內存裏面長成這樣
C語言會認爲var是char型的,取出一個字節當作var的值,也就是把0x2b送給var,我們把var用%c輸出,就是輸出了0x2b這個ASCII碼所代表的字符。就是“+”號。
五、
好吧,再這麼整下去也沒完了,下面用一個數組定義來終結此文吧。
彙編語言代碼和上一個一樣,
.fill 10,2,43
C語言修改成:
#include <stdio.h> typedef char CHARARR[20]; //CHARARR是一個類型別名,用它定義的每一個變量都是包含20個字符的數組 extern CHARARR var; //var被定義爲CHARARR類型,是一個包含20個元素的char型數組。 void main() { printf("sizeof(var)=%d\n",sizeof(var)); int i=0; while(i<=19) { printf("[%c]", var[i]); //用[]括起來更容易看出輸出現象 i++; } printf("\n"); }
我們讓var成爲數組,含有20個元素,正好把彙編裏面的 10單元x2字節 共計20個字節包括了。
然後用循環逐個輸出,爲什麼要這麼做而不用%s呢,因爲數組裏有很多字節是0x00,這是字符串終止標誌。%s會被打斷的。
結果如下:
可以看到和預計的一樣,20個元素以ASCII碼 0x2b 0x00 0x2b 0x00。。。。這樣的數組順序挨個輸出。
講完了,C語言和彙編語言結合起來是不是強大到了難以想象的地步,隨心所欲操縱內存數據。