技術員聯(lián)盟提供win764位系統(tǒng)下載,win10,win7,xp,裝機純凈版,64位旗艦版,綠色軟件,免費軟件下載基地!

當前位置:主頁 > 教程 > 服務器類 >

Linux下的AT&T語法

來源:技術員聯(lián)盟┆發(fā)布時間:2018-10-22 06:02┆點擊:

  學習這么長時間,一直在C語言這一層面上鉆研和打拼,日積月累,很多關于C的疑惑在書本和資料中都難以找到答案。程序員是追求完美的一個種群,其頭 腦中哪怕是存在一點點的思維黑洞都會讓其坐臥不寧。不久前在itput論壇上偶得《Computer Systems A Programmer's Perspective》(以下稱CS.APP)這本經(jīng)典好書,中文有翻譯的《深入理解計算機系統(tǒng)》。是遂連夜拜讀以求解惑。雖說書中沒有能正面的回答我的一些疑惑,但是它卻為我指明了一條通向 “無惑”之路 -- 這就是打開匯編之門。

  匯編語言是一門非常接近機器語言的語言,其語句與機器指令之間的對應關系更加簡單和清晰。打開匯 編之門不僅僅能解除高級語言給你帶來的疑惑,它更能讓你更加的理解現(xiàn)代計算機的運行體系,還有一點更加重要的是它給你帶來的是一種自信的感覺,減少了你在 高處搖搖欲墜的恐懼,響應了侯捷老師的“勿在浮沙筑高臺”的號召?,F(xiàn)在學習匯編的目的已與以前大大不同了。正如CS.APP中所說那樣“程序員學習匯編的 需求隨著時間的推移也發(fā)生了變化,開始時是要求程序員能直接用匯編編寫程序,現(xiàn)在則是要求能夠閱讀和理解優(yōu)化編譯器產(chǎn)生的代碼”。能閱讀和理解,這也恰恰 是我的需求和目標。

  以前接觸過匯編,主要是Microsoft MASM宏匯編,不過那時的認識高度不夠加上態(tài)度不端正,錯失了一個很好的學習機會?,F(xiàn)在絕大部分時間是使用GCC在Unix系列平臺上工作,選擇匯編語 言當然是GNU匯編了,恰好CS.APP中使用的也是GNU的匯編語法。由于學習匯編的主要目的還是“解惑”,所以形式上多是以C代碼和匯編代碼的比較。

  1、匯編讓你看到更多

  隨 著你使用的語言的層次的提高,你眼中的計算機將會越來越模糊,你的關注點也越來越遠離語言本身而靠近另一端“問題域”,比如通過JAVA,你更多看到的是 其虛擬機,而看不到真實的計算機;通過C,你看到的也僅僅是內(nèi)存一層;到了匯編語言,你就可以深入到寄存器一層自由發(fā)揮了。匯編程序員眼里的“獨特風景” 包括:

  a) “程序計數(shù)器(%eip)” -- 一個特殊寄存器,其中永遠存儲下一條將要執(zhí)行的指令的地址;

  b) 整數(shù)寄存器 -- 共8個,分別是%eax、%ebx、%ecx、%edx、%esi、%ebi、%esp和%ebp,它們可以存整數(shù)數(shù)據(jù),可以存地址,也可以記錄程序狀態(tài) 等。早期每個寄存器都有其特殊的用途,現(xiàn)在由于像linux這樣的平臺多采用“平面尋址[1]”,寄存器的特殊性已經(jīng)不那么明顯了。

  c) 條件標志寄存器 -- 保存最近執(zhí)行的算術指令的狀態(tài)信息,用來實現(xiàn)控制流中的條件變化。

  d) 浮點數(shù)寄存器 -- 顧名思義,用來存放浮點數(shù)。

  雖說寄存器的特殊性程度已經(jīng)弱化,但是實際上每個編譯器在使用這些寄存器時還是遵循一定的規(guī)則的,以后再說。

  2、初窺匯編

  下面是一個簡單的C函數(shù):

  void dummy() {

  int a = 1234;

  int b = a;

  }

  我們使用gcc加-S選項將之轉(zhuǎn)換成匯編代碼如下(省略部分內(nèi)容):

  movl $1234, -4(%ebp)

  movl -4(%ebp), %eax

  movl %eax, -8(%ebp)

  看 了一眼又一眼,還是看不懂,只是發(fā)現(xiàn)些熟悉的內(nèi)容,因為上面提過如%ebp、%eax等。這只是個引子,讓我們感性的認識一下匯編的“容貌”。我們一點點 地來看。咋看一眼匯編代碼長得似乎很相似,沒錯,匯編代碼就是一條一條的“指令+操作數(shù)”的語句的集合。匯編指令是固定的,每條指令都有其固定的用途,而 操作數(shù)表示則有多種類型。

  1) 操作數(shù)表示

  大部分匯編指令都有一個或多個操作數(shù),包括指令操作中的源和目的。一條標準的指令格式大 致是這樣的:“指令 + 源操作數(shù) + 目的操作數(shù)”,其中源操作數(shù)可以是立即數(shù)、從寄存器中讀出的數(shù)或從內(nèi)存中讀出的數(shù);而目的操作數(shù)則可以是寄存器或內(nèi)存。按這么一分類,操作數(shù)就大致有三 種:

  a) 立即數(shù)表示法 -- 如“movl $1234, -4(%ebp)”中的“$1234”,就是一個立即數(shù)作為操作數(shù),按照GNU匯編語法,立即數(shù)表示為“$+整數(shù)”。立即數(shù)常用來表示代碼中的一些常數(shù), 如上例中的“$1234”。注意一點的是立即數(shù)不能作為目的操作數(shù)。

  b) 寄存器表示法 -- 這種比較簡單,它就是表示寄存器之內(nèi)容。如上面的“movl -4(%ebp), %eax”中的%eax就是使用寄存器表示法作源操作數(shù),而“movl %eax, -8(%ebp)”中的%eax則是使用寄存器表示法作目的操作數(shù)。