快速入門(mén)Linux下GDB和匯編開(kāi)發(fā)工具

文章也同時(shí)在個(gè)人博客 http://kimihe.com/更新

引言

本文亦是《讀筆 匯編語(yǔ)言-基于Linux環(huán)境(第7章-跟蹤指令:與機(jī)器指令親密接觸I)》找颓。

本文將會(huì)以一個(gè)簡(jiǎn)單的.ASM程序援奢,step by step地幫助大家快速入門(mén)GDB何暇,并通過(guò)GDB調(diào)試散吵,深入底層闡述高級(jí)語(yǔ)言(如C語(yǔ)言)中循環(huán)結(jié)構(gòu)和指針的由來(lái)。

通過(guò)閱讀本文曙旭,你將知道:

  • 如何快速在Linux下進(jìn)行匯編開(kāi)發(fā)涯贞。
  • 如何快速入門(mén)GDB。
  • 高級(jí)語(yǔ)言循環(huán)結(jié)構(gòu)的原理星持。
  • 指針到底是什么抢埋。

構(gòu)建匯編程序

原料

  • Linux環(huán)境,筆者是Ubuntu 12.04 LTS。
  • 安裝NASM: 新立得軟件包管理器揪垄。
  • 安裝Kate編輯器和KWrite編輯器: 新立得軟件包管理器穷吮。
  • 安裝konsole:> sudo apt-get install konsole

第一個(gè)匯編程序

切到你喜歡的工作目錄下,執(zhí)行> kate以啟動(dòng)Kate編輯器饥努,啟動(dòng)后界面類似于這樣:

Kate

左側(cè)是導(dǎo)航欄捡鱼,右側(cè)是代碼編輯區(qū),下方是終端控制區(qū)(若要啟用此特性請(qǐng)務(wù)必先安裝konsle)肪凛。

新建一個(gè)文件堰汉,命名為sandbox.asm辽社,在其中輸入如下內(nèi)容:

section .data
    Snippet db "KANGAROO"
section .text
    global  _start
_start:
    nop
; Put your experiments between the two nops...
    mov ebx, Snippet
    mov eax, 8
DoMore: add byte [ebx], 32
    inc ebx
    dec eax
    jnz DoMore
; Put your experiments between the two nops...
    nop

這段代碼是我們第一個(gè)匯編小例子伟墙,用于闡明循環(huán)結(jié)構(gòu)的原理,請(qǐng)確保文章例子和你的完全一致滴铅。

循環(huán)結(jié)構(gòu)的原理

如果是首次接觸匯編戳葵,你可能會(huì)一頭霧水,在這里你不必在意匯編的語(yǔ)法汉匙,只需要理解我對(duì)代碼的說(shuō)明即可拱烁。

此處請(qǐng)先注意語(yǔ)句Snippet db "KANGAROO",其中Snippet代表一個(gè)字符串噩翠,內(nèi)容為KANGAROO戏自。然后注意語(yǔ)句mov ebx, Snippet,這一步相當(dāng)于獲取字符串的首地址伤锚。緊接著的mov eax, 8用于獲知字符串的長(zhǎng)度擅笔。這兩步很平常,高級(jí)語(yǔ)言的字符串處理也需要獲知字符串地址以及相應(yīng)的長(zhǎng)度屯援。

然后請(qǐng)關(guān)注如下四條語(yǔ)句:

DoMore: add byte [ebx], 32
        inc ebx
        dec eax
        jnz DoMore

此處的jnz DoMore語(yǔ)句便是循環(huán)結(jié)構(gòu)的核心猛们。其含義是:jnz(Jump if Not Z-Flag)進(jìn)行判斷,如果零標(biāo)志位ZF不為0狞洋,就跳轉(zhuǎn)到DoMore語(yǔ)句處弯淘。

于是你可以想到,只要這個(gè)ZF標(biāo)志位不是0吉懊,程序就會(huì)不停地循環(huán)跳轉(zhuǎn)(loop)庐橙,循環(huán)結(jié)構(gòu)由此而來(lái)。

你可能會(huì)想問(wèn):什么時(shí)候ZF會(huì)變成0借嗽?這個(gè)問(wèn)題很好态鳖,試想一下高級(jí)語(yǔ)言的while(n)循環(huán),我們必然需要一個(gè)操作步驟來(lái)改變n的值淹魄,使其在某一時(shí)刻變成0郁惜,從而跳出while。

此處,眼尖的讀者可能發(fā)現(xiàn)了dec指令兆蕉,還記得一開(kāi)始的獲取字符串長(zhǎng)度為8嗎羽戒?我們把8存在了eax寄存器中(如果你不清楚寄存器是什么,也沒(méi)有關(guān)系虎韵,把它想象成一個(gè)可以存放數(shù)值容器即可)易稠。通過(guò)dec eax指令,我們會(huì)不斷地對(duì)eax中的8進(jìn)行遞減包蓝,類似于int eax = 8; eax--;總有一天驶社,eax中的值會(huì)從8減到0,此時(shí)我們的x86 Intel CPU就會(huì)執(zhí)行一項(xiàng)既定的操作测萎,把ZF標(biāo)志設(shè)為1,以代表此標(biāo)志位處于激活狀態(tài)亡电。于是,jnz在判斷的時(shí)候就發(fā)現(xiàn)ZF已經(jīng)被激活為1了硅瞧,不需要再跳轉(zhuǎn)份乒,循環(huán)結(jié)果宣告結(jié)束。

此外腕唧,不知道你有沒(méi)有對(duì)于jnz跳轉(zhuǎn)指令產(chǎn)生一些聯(lián)想:它是不是很像函數(shù)指針或辖?(jnz到一個(gè)地方,那個(gè)地方叫做DoMore枣接,然后執(zhí)行一段過(guò)程颂暇。)當(dāng)然關(guān)于函數(shù)指針詳細(xì)的說(shuō)明,本文篇幅可就不夠了但惶,筆者會(huì)考慮以后單獨(dú)寫(xiě)一篇文章詳細(xì)說(shuō)明耳鸯,敬請(qǐng)期待~

什么是指針

有讀者可能會(huì)問(wèn),還有兩行代碼沒(méi)有解釋呢榆骚。不要著急片拍,這兩行代碼蘊(yùn)含著指針的奧秘。聽(tīng)起來(lái)可能有點(diǎn)令人驚奇妓肢,但實(shí)際情況確實(shí)如此捌省。讓我們來(lái)看一下這兩行代碼:

DoMore: add byte [ebx], 32
        inc ebx

注意add byte [ebx], 32這句話,它的專業(yè)術(shù)語(yǔ)叫做寄存器間接尋址碉钠。它是如此神奇纲缓,毫不夸張地說(shuō),如果沒(méi)有它喊废,我們?nèi)粘K?jiàn)的絕大部分程序?qū)㈦y以構(gòu)建祝高。

這句話解釋一下就是這樣:有一個(gè)內(nèi)存單元,它有一個(gè)byte大小的空間污筷,里面存有一個(gè)數(shù)值n(具體是多少工闺,現(xiàn)在不用關(guān)心)。把數(shù)值32 Add到這個(gè)n上,就是相當(dāng)于n+=32陆蟆。然后關(guān)鍵點(diǎn)來(lái)了雷厂,為了加上32,我們需要知道這個(gè)內(nèi)存區(qū)域在哪兒叠殷。在哪兒呢改鲫?在ebx里存著呢!

內(nèi)存就像一個(gè)個(gè)信箱林束,每個(gè)信箱都有自己的編號(hào)像棘,當(dāng)我們尋找自家的信箱時(shí),會(huì)根據(jù)信箱的編號(hào)去尋找它壶冒。這里ebx就存著我們要的內(nèi)存區(qū)域的編號(hào)缕题,這個(gè)編號(hào)叫做地址根據(jù)這個(gè)地址依痊,我們找到了那個(gè)內(nèi)存單元的具體位置避除,然后知道了其中存了一個(gè)數(shù)n,最后把32給加到了n上胸嘁。

這里,你應(yīng)該可以看到凉逛,我們并不是直接去訪問(wèn)那個(gè)數(shù)值n的性宏,而是先去找存放它的內(nèi)存單元。這里面存在一層間接状飞。正是有了這層間接毫胜,我們才能在高級(jí)語(yǔ)言中構(gòu)筑起各種華麗的調(diào)用操作。

于是指針的原理也顯而易見(jiàn)了诬辈,對(duì)于

char arr[4] = "abcd";
char *p = arr;
p+=3;
printf("*p: %c\\n", *p);

我們char *p = arr;操作定位的arr數(shù)組的首地址酵使。arr信箱有四個(gè)格子,我們定位到第一個(gè)焙糟,然后p+=3;并不是直接給信箱什么的加3口渔,這明顯不符合邏輯,而是操作信箱的編號(hào)(地址)穿撮。加3意味著往后數(shù)三個(gè)缺脉,定位到第四個(gè)格子,最后打印里面的東西悦穿,就是字符d攻礼。

內(nèi)存中的數(shù)據(jù)有兩種,分別是數(shù)據(jù)地址栗柒,數(shù)據(jù)就是普通的變量礁扮,地址就是指針。希望你不要混淆。

使用GDB

下面進(jìn)入最后一個(gè)知識(shí)點(diǎn)太伊,快速入門(mén)GDB负蠕。在此之前,我們需要把編寫(xiě)的.ASM程序編譯鏈接運(yùn)行起來(lái)倦畅。你可能聽(tīng)說(shuō)過(guò)Linux下的make工具遮糖,說(shuō)白了就是個(gè)配置文件,告訴NASM叠赐,gcc等編譯器怎么有效地編譯我們的源碼欲账,避免重復(fù)勞動(dòng)。make配合makefile文件工作芭概,如果你不知道這到底是什么赛不,也完全沒(méi)有關(guān)系,畢竟這不是本文的重點(diǎn)罢洲,只是順帶提一下踢故。

你可以在Kate編輯器中再新建一個(gè)文本,名為makefile惹苗,請(qǐng)確保它和我們的sandbox.asm在同一個(gè)目錄下殿较。向其中輸入如下內(nèi)容:

sandbox: sandbox.o
    ld -o sandbox sandbox.o
sandbox.o: sandbox.asm
    nasm -f elf64 -g -F stabs sandbox.asm -l sandbox.lst

你可以完全不必理會(huì)這四句話到底代表了什么,只需要明白它們會(huì)讓NASM正確地生成我們的.ASM程序桩蓉。

有了這個(gè)makefile淋纲,接下來(lái)可以在Kate編輯器下方的terminal中輸入> make -k,或者你自己?jiǎn)?dòng)shell院究,切到你的工作目錄洽瞬,執(zhí)行上述命令。如果正確編譯完成业汰,那么看起來(lái)就像這樣子:

GDB_terminal

接下來(lái)伙窃,我們要使用GDB了,在Terminal中鍵入:> gdb sandbox以啟用gdb調(diào)試样漆。

調(diào)試为障,我們一般都會(huì)需要設(shè)置斷點(diǎn),來(lái)看看各變量的情況氛濒。這里我們已經(jīng)更加深入到底層产场,不在內(nèi)存中操作了,直接來(lái)到了CPU內(nèi)部的寄存器中舞竿。鍵入:> b 10即在DoMore: add byte [ebx], 32語(yǔ)句處加入斷點(diǎn)京景。

然后,鍵入:> r然程序開(kāi)始運(yùn)行骗奖。程序會(huì)停在DoMore語(yǔ)句那里确徙,看起來(lái)就像這樣:

step1

接著醒串,鍵入:i r查看個(gè)寄存器狀態(tài),就像這樣:

step2

你可以看到高亮的綠色部分鄙皇,rax中存有字符串長(zhǎng)度8芜赌,rbx中存有字符串地址。

啥伴逸?為什么不是eax和ebx缠沈?嗯,很有價(jià)值的問(wèn)題错蝴,eax和ebx是32位CPU架構(gòu)下的寄存器洲愤,而如今64位已經(jīng)普及,我們的寄存器也隨之升級(jí)了顷锰。

然后按一下Enter鍵柬赐,或者輸入return,可以看到下一頁(yè)未顯示完全的一些寄存器:

step3

注意到綠色高亮部分的eflags標(biāo)志位官紫,我們發(fā)現(xiàn)其中除了IF什么都沒(méi)有肛宋,這表明我們上文提到的ZF標(biāo)志還沒(méi)有被激活。

接下來(lái)束世,鍵入:s酝陈,它代表單步執(zhí)行一行語(yǔ)句,請(qǐng)先執(zhí)行一次良狈,然后再鍵入:i r看一下結(jié)果寄存器狀態(tài):

step4

可以看到rax寄存器內(nèi)部的值從8減到7后添,表明執(zhí)行了一次循環(huán)中的dec指令。接下來(lái)你可以繼續(xù)單步執(zhí)行7次薪丁,即鍵入7次s。每一次都查看一下寄存器的狀態(tài)馅精,你會(huì)發(fā)現(xiàn)rax不斷遞減严嗜,直到0。7次單步之后洲敢,再次鍵入i r進(jìn)行查看:

step5

你會(huì)發(fā)現(xiàn)rax變成0了漫玄,此時(shí)Enter到下一頁(yè),我們發(fā)現(xiàn):

step6

沒(méi)錯(cuò)压彭!eflags中出現(xiàn)了ZF標(biāo)志睦优,表明其被激活,這樣jnz就不會(huì)再跳到DoMore壮不,循環(huán)終于結(jié)束了汗盘。

最后請(qǐng)鍵入q,然后y退出GDB询一。我們的GDB快速入門(mén)到此告一段落隐孽。

留一個(gè)小問(wèn)題

看到這兒癌椿,相信你已經(jīng)大概理解了循環(huán)結(jié)構(gòu)和指針的原理,對(duì)匯編工具以及GDB的使用也略知一二菱阵。那么我在這里提一個(gè)小問(wèn)題:這段匯編代碼到底是做什么的踢俄?請(qǐng)你積極思考哦~

答案我會(huì)在留言中說(shuō)明。

總結(jié)

本篇文章通過(guò)Linux下的一個(gè)最簡(jiǎn)易的匯編開(kāi)發(fā)流程晴及,帶領(lǐng)大家熟悉了開(kāi)發(fā)工具的使用都办,并入門(mén)了GDB這一神器。同時(shí)通過(guò)閱讀匯編代碼虑稼,從底層理解了循環(huán)結(jié)構(gòu)和指針的原理琳钉。希望對(duì)大家有所啟迪,感謝閱讀动雹!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末槽卫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胰蝠,更是在濱河造成了極大的恐慌歼培,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茸塞,死亡現(xiàn)場(chǎng)離奇詭異躲庄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钾虐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)噪窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人效扫,你說(shuō)我怎么就攤上這事倔监。” “怎么了菌仁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵浩习,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我济丘,道長(zhǎng)谱秽,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任摹迷,我火速辦了婚禮疟赊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘峡碉。我一直安慰自己近哟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布异赫。 她就那樣靜靜地躺著椅挣,像睡著了一般头岔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鼠证,一...
    開(kāi)封第一講書(shū)人閱讀 52,584評(píng)論 1 312
  • 那天峡竣,我揣著相機(jī)與錄音,去河邊找鬼量九。 笑死适掰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荠列。 我是一名探鬼主播类浪,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肌似!你這毒婦竟也來(lái)了费就?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤川队,失蹤者是張志新(化名)和其女友劉穎力细,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體固额,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眠蚂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斗躏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逝慧。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖啄糙,靈堂內(nèi)的尸體忽然破棺而出笛臣,到底是詐尸還是另有隱情,我是刑警寧澤隧饼,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布捐祠,位于F島的核電站,受9級(jí)特大地震影響桑李,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜窿给,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一贵白、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧崩泡,春花似錦禁荒、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)勃痴。三九已至,卻和暖如春热康,著一層夾襖步出監(jiān)牢的瞬間沛申,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工姐军, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铁材,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓奕锌,卻偏偏與公主長(zhǎng)得像著觉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惊暴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容