匯編入門

CPU在運行的時候實際上是讀取指令并一條一條的執(zhí)行诺核,而這些指令是二進制的衔肢,也就是機器碼,但是由于二進制的語言對人類的可讀性不好脖含,因此便出現(xiàn)了匯編語言罪塔,一般而言,匯編語言可以看作是機器碼的文本格式养葵,它們間可以相互轉換征堪,還原成機器碼后便可以被CPU執(zhí)行。其特點有:

  • 可直接訪問关拒、控制各種硬件設備佃蚜。比如存儲器、CPU等着绊,能最大限度地發(fā)揮硬件的功能
  • 能夠不受編譯器的限制谐算,對生成的二進制代碼進行完全的控制
  • 目標代碼簡短,占用內存少归露,執(zhí)行速度快
  • 匯編指令是機器指令的助記符洲脂,同機器指令一一對應。每種CPU都有自己的機器指令集/匯編指令集剧包,所以* 匯編語言不具備可移植性
  • 匯編語言知識點過多恐锦,開發(fā)者需要對CPU等硬件結構有所了解往果,不宜于編寫、調試一铅、維護
  • 不區(qū)分大小寫陕贮,比如mov和MOV是一樣的

對于一個使用高級語言的程序員來說,匯編語言不需要自己編寫馅闽,但是至少需要看得懂飘蚯,知道其中的原理,才能更好的排查問題福也。

總的來說局骤,匯編代碼是被CPU一條一條地取出執(zhí)行的,CPU會通過這些指令來對寄存器和內存等進行操作暴凑。因此學好匯編峦甩,需要對寄存器和內存有一定的了解

寄存器

由于CPU的運算速度通常都比內存讀寫速度要快,而CPU要運算的時候都要從內存中讀取數(shù)據(jù)现喳。為了節(jié)省時間凯傲,一般CPU都自帶緩存,除此之外嗦篱,還自帶了寄存器冰单,用來存儲頻繁使用的數(shù)據(jù),此外CPU還會使用寄存器與內存交換數(shù)據(jù)灸促。

不同CPU里面的寄存器名字和數(shù)量都不一致诫欠,寄存器的用法基本都是想通的,但是大致上可以分成以下種:

通用寄存器

主要是AX浴栽,BX,CX,DX等等

指令寄存器

也就是IP,用于記錄現(xiàn)在程序執(zhí)行到哪

指針寄存器

主要是棧指針寄存器SP和椈牡穑基指針寄存器BP,每當有數(shù)據(jù)入棧/出棧的時候典鸡,都會導致SP改變

段寄存器

標志段的開始被廓,主要有CS,DS,SS,ES等等

當然還有許多別的種類的寄存器沒有提及,比如索引寄存器(SI,DI)萝玷,而且嫁乘,上述的通用寄存器部分又有各自的用途,比如AX用于累加和中斷球碉,CX用于計數(shù)蜓斧、循環(huán)等等。實際上汁尺,如果僅是看代碼的話法精,大部分寄存器在通常情況下都可以看作通用寄存器多律。因為它們存放的數(shù)值被匯編代碼的指令控制的痴突。我們只需要知道的特殊的寄存器(比如IP,SP)即可搂蜓。

內存分段

在程序運行的時候,系統(tǒng)會給程序分配一定的內存空間辽装,這些內存空間會分成好幾段:

代碼段

存放匯編指令帮碰,其段寄存器為CS,此外還有指令寄存器IP,CPU就是從這個段讀取指令

數(shù)據(jù)段

存放全局變量拾积,可以根據(jù)這些變量有沒有被初始化進一步劃分殉挽,其段寄存器為DS

堆棧段

用來存放程序運行期間產生的變量,又分成堆和棧拓巧,其中棧用于存放函數(shù)中的局部變量斯碌,而堆用來存放動態(tài)分配的變量,堆棧段的寄存器為SS,另外有個SP的寄存器永遠指向棧頂。堆和棧的具體區(qū)別如下圖肛度。


image
擴展段

保存程序其它相關的信息傻唾,其段寄存器為ES

常用匯編指令

每一個處理器匯編指令都不太一樣,但是其基本功能都是相通的承耿,這里僅以8086處理器的指令集為例:

mov

傳送指令冠骄,其用法為mov a,b加袋,指的是將b的值賦值給a

add

加法凛辣,其用法為add a,b,將b的值加上a的值賦值給a职烧,即a = a + b

sub

減法扁誓,其用法為sub a, b,與上面類似,相當于a = a - b

cmp

比較阳堕,其用法為cmp a, b,比較a和b的大小跋理,其比較的結果存儲在標志寄存器中。

jmp

無條件轉移指令恬总,通過修改IP和CS寄存器前普,使程序跳到目標地址運行

jcc

條件轉移指令,jcc包含一系列的指令壹堰,通過判斷標志寄存器的狀態(tài)決定是否跳轉

call

調用函數(shù)拭卿,程序會調到函數(shù)入口執(zhí)行

ret

函數(shù)返回

高級語言程序結構對應的匯編語言

下面看一下程序的順序結構、選擇結構贱纠、循環(huán)結構下的匯編語言是怎么樣的峻厚,本文所使用的語言為C++,處理器為x86_64谆焊,其指令集跟上面的不太一樣惠桃,而且,其用法跟8086是相反的。

順序結構

在main函數(shù)里面寫上如下代碼:

int a = 5;
int b = 1;
a++;
b += a;

其對應的匯編語言是這樣的

;a = 5
0x100000f94 <+20>: movl   $0x5, -0x14(%rbp) ;將5賦值給偏移量為-0x14的內存區(qū)域辜王,也就是說-0x14代表a
;b = 1
0x100000f9b <+27>: movl   $0x1, -0x18(%rbp) ;將1賦值給偏移量為-0x18的內存區(qū)域劈狐,也就是說-0x18代表b
;a++
0x100000fa2 <+34>: movl   -0x14(%rbp), %edi ;將a賦值給edi寄存器
0x100000fa5 <+37>: addl   $0x1, %edi ; edi寄存器加1
0x100000fa8 <+40>: movl   %edi, -0x14(%rbp) ;將edi寄存器賦值給a,這個時候完成了a++的操作
;b += a
0x100000fab <+43>: movl   -0x14(%rbp), %edi ;將a賦值給edi寄存器
0x100000fae <+46>: addl   -0x18(%rbp), %edi ;edi加上b的值
0x100000fb1 <+49>: movl   %edi, -0x18(%rbp) ;將edi寄存器賦值給a,這個時候完成了b += a的操作

選擇結構

同樣,在main函數(shù)中寫一個簡單的選擇結構

int a = 5;
if (a>3) {
    a++;
}else {
    a--;
}

對應的匯編代碼如下:

0x100000f82 <+18>: movl   $0x5, -0x14(%rbp)  ;a = 5
0x100000f89 <+25>: cmpl   $0x3, -0x14(%rbp)  ;a 和 3比較
0x100000f8d <+29>: jle    0x100000fa1        ;如果小于等于呐馆,就跳到0x100000fa1執(zhí)行
;下面是a++的實現(xiàn)
0x100000f93 <+35>: movl   -0x14(%rbp), %eax
0x100000f96 <+38>: addl   $0x1, %eax
0x100000f99 <+41>: movl   %eax, -0x14(%rbp)
0x100000f9c <+44>: jmp    0x100000faa        ; 實現(xiàn)后程序跳轉到0x100000faa執(zhí)行
;下面是a--
0x100000fa1 <+49>: movl   -0x14(%rbp), %eax  
0x100000fa4 <+52>: addl   $-0x1, %eax
0x100000fa7 <+55>: movl   %eax, -0x14(%rbp)
0x100000faa .....

顯然肥缔,匯編語言是使用cmp、jmp和jcc指令實現(xiàn)選擇結構的汹来。

循環(huán)機構

在main函數(shù)中寫一個簡單的循環(huán):

int i = 0;
while(1){
    i++;
    if(i>5){
        break;
    }
}

這里使用了while做循環(huán)续膳,實際上跟使用for循環(huán)的匯編代碼是差不多的。

0x100000f82 <+18>: movl   $0x0, -0x14(%rbp) ;i = 0
0x100000f89 <+25>: movl   -0x14(%rbp), %eax ;這里開始循環(huán)
0x100000f8c <+28>: addl   $0x1, %eax  
0x100000f8f <+31>: movl   %eax, -0x14(%rbp)
0x100000f92 <+34>: cmpl   $0x5, -0x14(%rbp)
0x100000f96 <+38>: jle    0x100000fa1               
0x100000f9c <+44>: jmp    0x100000fa6  ;如果i>5,則跳出循環(huán)              
0x100000fa1 <+49>: jmp    0x100000f89  ;跳回0x100000f89收班,繼續(xù)循環(huán)
0x100000fa6 ....

可以看出坟岔,循環(huán)結構也是通過cmp、jmp和jcc指令實現(xiàn)的摔桦。

參考文獻

iOS之底層匯編(一)

程序內存空間(代碼段炮车、數(shù)據(jù)段、堆棧段)

8086匯編指令全集

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末酣溃,一起剝皮案震驚了整個濱河市瘦穆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赊豌,老刑警劉巖扛或,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異碘饼,居然都是意外死亡熙兔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門艾恼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來住涉,“玉大人,你說我怎么就攤上這事钠绍∮呱” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵柳爽,是天一觀的道長媳握。 經常有香客問我,道長磷脯,這世上最難降的妖魔是什么蛾找? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮赵誓,結果婚禮上打毛,老公的妹妹穿的比我還像新娘柿赊。我一直安慰自己,他們只是感情好幻枉,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布闹瞧。 她就那樣靜靜地躺著,像睡著了一般展辞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上万牺,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天罗珍,我揣著相機與錄音,去河邊找鬼脚粟。 笑死覆旱,一個胖子當著我的面吹牛,可吹牛的內容都是我干的核无。 我是一名探鬼主播扣唱,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼团南!你這毒婦竟也來了噪沙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吐根,失蹤者是張志新(化名)和其女友劉穎正歼,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拷橘,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡局义,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了冗疮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萄唇。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖术幔,靈堂內的尸體忽然破棺而出另萤,到底是詐尸還是另有隱情,我是刑警寧澤诅挑,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布仲墨,位于F島的核電站,受9級特大地震影響揍障,放射性物質發(fā)生泄漏目养。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一毒嫡、第九天 我趴在偏房一處隱蔽的房頂上張望癌蚁。 院中可真熱鬧幻梯,春花似錦、人聲如沸努释。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伐蒂。三九已至煞躬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逸邦,已是汗流浹背恩沛。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缕减,地道東北人雷客。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像桥狡,于是被迫代替她去往敵國和親搅裙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容