本節咱們看看X86指令集以及X86的硬件體系架構。在彙編語言中最多見的指令就是mov,他將數據從一個地方轉移到指定位置,該指令能將數據轉移到特定位置的內存或是給定寄存器。mov指令的格式爲(mov 目的,源頭),源頭指的是要被挪到的數據,目的是數據被挪動的目的地, 咱們看幾個具體例子:
mov eax, ebx (把寄存器ebx中的數據拷貝到eax寄存器)
mov eax, 0x42 (把數值0x42賦值給eax寄存器)
mov eax, [0x4037c4](把地址爲0x4037c4的4字節數據拷貝到eax寄存器]
mov eax, [ebx] (先從寄存器ebx中獲取數值,而後找到該數值對應的內存地址,接着再把地址所在處4字節數據賦值給寄存器eax)
mov eax, [ebx + esi*4] (取出ebx中的數值,取出esi寄存器中的數值,將後者乘以4後加上前者,所得結果做爲內存地址,並把給定地址的4字節數據拷貝到eax寄存器)
另外一個跟mov指令很像的是指令lea,lea eax, [ebx+8],其做用爲把ebx寄存器的值加上8後所得結果放入eax,這裏須要注意區別,利潤mov eax, [ebx+8]是把ebx的值加上8,所得結果做爲內存地址,而後將地址所在處的4字節數據轉移到eax寄存器,所以指令lea eax, [ebx+8]等價於mov eax, ebx+8,這是一個容易混淆之處,咱們看下圖會更清楚一些:
左邊是寄存器的數值,右邊是對應內存地址的數值。對於指令lea ebx, [eax5+5],它會計算0x00000005+5=5,而後把結果5放到寄存器ebx。lea指令主要用於加快計算速度,要否則咱們完成給定計算須要使用不少條指令,例如先使用mul 5將eax裏面的數值乘以5,而後add eax, 5,將5加到eax,而後mov ebx, eax,將eax中存儲的數值挪動到ebx,所以不使用lea指令的話,咱們須要使用4到5條指令才能達到相同效果。
x86指令集中有很多專門用於進行數值運算。從加減乘除到各類二進制操做,指令add用於執行加法操做,它的格式爲:add destination, value 也就是把value對應的數值家到destination對應的數值上,後者能夠是內存,也能夠是特定寄存器。同理sub指令用於進行減法操做,特別要注意的是,該指令會修改兩個重要的標誌位寄存器,分別爲ZF和CF,若是作減法後所得結果爲0,ZF寄存器就好設置爲1,若是sub destination ,value這條指令執行時,destination對應的數值小於value,那麼CF寄存器就會設置爲1,咱們看幾條運算指令的例子:
sub eax, 0x10 把eax寄存器裏面的數值減去0x10
add eax, ebx 把ebx寄存器裏面的數值添加到eax寄存器
inc edx,將edx寄存器裏面的數值增長1
dec ecx 將ecx寄存器裏面的數值減小1
乘除法指令分別爲mul, div,這兩條指令的特色是指對應一個操做數,例如mul 5是指將eax寄存器中的數值乘以5,注意eax沒有出如今指令中,對mul指令而言,它默認就是講eax的數值乘以給定數值。因此在執行mul指令前,咱們必須預先存儲好eax指令中的數值。mul指令執行後所得結果會被當成一個64位數值分別存儲在兩個寄存器中,他們分別爲edx和eax,edx存儲高32位,eax存儲低32位,假設執行mul指令後,所得結果爲5,000,000,000,該數值早已超過32位,所以必須使用兩個32位的寄存器共同存儲,其存儲結果以下:
div指令使用與mul同樣,只是結果的存儲正好相反。作完除法後所得結果爲64位,那麼除法的結果存儲在eax,除法所得餘數存儲在edx,所以在執行mul或div指令時,須要預先存儲好兩個寄存器的數值,要否則指令執行後原來存儲的數值會被沖刷掉。在高級語言編程中咱們計算餘數時,例如x = x%b,那麼底層就好使用div指令,而後把寄存器edx中的數值轉移到x變量對應的地址。
除了運算指令外,二進制操做指令也常常用到,例如or, and 和xor等。這些指令的用法與add,sub相似,xor指令在彙編中常常使用,它經常使用於清零,例如xor eax, eax就是把eax寄存器的數值設置爲0,固然咱們也能夠使用mov eax, 0來清零,可是前者轉換爲機器碼時只有2字節,後者須要5字節。
指令shr,shl用於進行挪位操做,例如shr destination, count把destination對應的數值向右移動count位,shl destination, count 把destination的值向左邊挪動count位,挪動後空出來的比特位用0來補齊。例如 shr 1000, 1,執行後數值變爲0100。指令ror和rol也用來挪動二進制比特位,於shr,shl不一樣的是,他們不是用0彌補而是把被挪走的比特位放到前面,例如ror 10101, 1執行後所得結果爲11010.挪位指令一般對應對應高級語言的>>和<<操做符。在進行反彙編分析是時,若是咱們看到一系列shr, shl, ror,rol等指令,這意味着代碼極有可能在進行加解密操做。
最後一條操做符指令就是NOP,它什麼都不作,這條指令常常用於進行緩衝區溢出攻擊,這條指令的做用在後續章節中會詳細講解。
本文分享自微信公衆號 - Coding迪斯尼(gh_c9f933e7765d)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。編程