正式工做以後打算着手作一些逆向方面的研究,聽前輩們的建議,必須先把彙編學會,因而我用第一個月把《彙編語言》(第三版-王爽著)看了一遍,可是人的記憶力是有限的,因此打算以博客的形式再回憶一遍,相信經過這種形式,能讓本身對知識理解的更加模塊化和具體化,也方便本身往後複習,同時也方便了看到這篇博客的同道中人。編程
彙編語言在整個計算機編程語言中的地位能夠說是沒什麼用,不多有人會直接拿彙編語言去寫項目,若是這麼幹的話,不得麻煩死(可是不排除確實有這種需求的時候的作法)。更多時候彙編語言的使用場景是在反編譯別人的二進制代碼以後,對彙編代碼的邏輯還原,而且對於計算機系統總體的理解,我相信沒有什麼比學習彙編語言更快、更好。編程語言
寄存器:用於存放cpu的數據信息,共14個,分別是:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW。模塊化
字節、字和雙字:1雙字(DWROD)=2字(WORD)=4字節(byte)。1字節(byte)=8位(bit),好比,寄存器ax是16位寄存器,在內部能夠在分爲ah和al,分別表明高8位和低8位。oop
內存訪問:通常利用寄存器ds,es,ss才能夠間接訪問內存,好比要訪問2000:0200位置的數據,並將該位置的數據傳送入ax,應該這樣:學習
mov ax,2000h mov ds,ax mov si,200h mov ax,ds:[si]
assume cs:code stack segment db 128 dup (0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,128 ;目前棧頂在ss:sp處(即stack:128),也就是上面定義的stack中的128字節 mov ax,'a' push ax ;將'a'入棧,棧頂在ss:sp處(即stack:126) push ax pop bx ;出棧,將數據保存在bx中 mov ax,4c00h int 21h code ends end start
ZF:是否爲0 PF:1的個數是否爲偶數 SF:是否爲負數 有符號整數,只看結果是否是大於7,也就是首位是否是0 CF:是否存在進位或借位(無符號整數) 直接進行無符號運算,首位進位就置1 OF:是否存在溢出(有符號整數) 16位cpu,有符號溢出範圍79H(127),-80H(128) DF:方向標誌位,與movsb配合使用
數據傳送指令: mov:數據傳送 示例:mov ax,bx 說明:將bx中的數據傳送到ax中,由於使用的是ax和bx,因此數據的長度是16位,下面的例子都相同,若是有操做數據中有寄存器,那麼按照寄存器的數據長度計算 push:入棧 示例:push ax 解釋:將ax的數據入棧,傳送到ss:sp棧頂處 pop:出棧 示例:pop ax 解釋:將ss:sp位置的數據出棧,傳送入ax中 pushf:全部標誌位入棧 示例:pushf 解釋:標誌位入棧,防止後面的操做對標誌位產生影響的一般作法 popf:標誌位出棧 示例:popf 解釋:標誌位出棧,用於還原入棧的標誌位 xchg:交換,目前沒用到
算數運算指令 add:加法 示例:add ax,2 解釋:將ax中的數據加2,即ax+0002h sub:減法 示例:sub ax,2 解釋:將ax中的數據減2,即ax-0002h adc:加法(帶符號位) 示例:adc ax,2 ;CF=1 解釋:將ax中的數據加3,即ax+0002h+1h sbb:減法(帶符號位) 示例:sbb ax,2 ;CF=1 解釋:將ax中的數據減3,即ax-0002h-1h inc:自增 示例:inc si 解釋:將si中的數據加1,經常使用在循環或條件轉移中 dec:自減 示例:dec ax 解釋:將ax中的數據減1 cmp:比較 示例:cmp ax,0 解釋:至關於減法,ax-0,只不過不影響寄存器的值,而隻影響標誌寄存器,由於條件轉移指令是依據標誌寄存器的指令,因此cmp常與條件轉移指令配合使用進行條件轉移 mul:乘法 示例:mul bx或mul bl 解釋:分爲兩種狀況: 1. 指令參數是8位寄存器如bl時,乘數1默認放在al寄存器中,另外一個乘數2放在8位寄存器如bl中,結果存在ax中 2. 指令參數是16位寄存器如bx時,乘數1默認放在ax寄存器中,另外一個乘數2是指定的16位寄存器如bx中的數據,結果的高16位存在dx,低16位存在ax中 div:除法 示例:div bx或div bl 解釋:一樣分爲兩種狀況: 1. 指令參數是8位寄存器時,被除數(除法前面那個數。。。)則爲16位,默認存放於ax中,除數則是存放於指定8位寄存器如bl中,結果爲:al存儲商,ah存儲餘數 2. 指令參數是16位寄存器時,被除數則爲32位,默認存放於ax和dx中,dx存高16位,ax存低16位,除數存放於指定16位寄存器如bx中,結果:ax存儲商,dx存儲餘數 aaa:目前沒有用到
邏輯指令 and:邏輯與 示例:and al,11011111b 解釋:示例中結果是將al中第6位置爲0,其餘位保持不變,經常使用與簡化運算如,將小寫字母轉化爲大寫字母,只須要將字母與11011111作邏輯與運算便可實現 or:邏輯或 示例:or al,00100000 解釋:示例中結果是將al中第6位置爲1,其餘位保持不變,一樣也能實現將大寫字母轉化爲小寫字母的簡化運算,須要將字母與00100000作邏輯或運算便可實現 not:邏輯非,不經常使用 示例: 解釋: xor:邏輯異或,目前不經常使用 示例: 解釋: test:不經常使用 shl:邏輯左移 示例:shl al,1或mov cl,3;shl al,cl 解釋:邏輯左移的意思就是左移後,移出的數據存放在標誌寄存器CF中,而最低位用0補齊,也分爲兩種狀況: 1. 左移1位:直接shl al,1便可 2. 左移超過1位:須要先將欲移動的位數據存入cl中,再經過左移cl個位的數據來實現 shr:邏輯右移 示例:shr al,1或move cl,2;shr al,cl 解釋:邏輯右移與邏輯左移相似,這裏就很少講了,一樣也是兩種狀況 sal sar rol ror rcl rcr
轉移指令 無條件轉移指令 jmp:無條件轉移指令 示例:jmp short s;s:inc ax 解釋:jmp轉移指令能夠實現段內短轉移、段內近轉移和段間轉移這三種基本需求 1. 段內短轉移:只對IP寄存器修改,修改範圍爲-128~127,也就是說向前最多轉移+127個字節,向後最多轉移-128個字節 2. 段內近轉移:與短轉移基本相同,不過是16位的位移,即修改IP的範圍是-32768~32767 3. 遠轉移(段間轉移):能夠轉移到指定的內存處,上面的兩個轉移只是在同一個段中的轉移,是根據位移定位的轉移方式,而遠轉移能夠指定轉移的目的地址 條件轉移指令 jcxz:若是cx寄存器的值爲0,則轉移到指定標號 示例:mov cx,0;jcxz s 解釋:若是條件知足cx寄存器的值爲0,則轉移到指定的標號處,經常使用的場景是:遍歷一個以'0'字符結尾的字符串,根據這個0判斷字符串是否到末尾的簡單實現方式 je:若是cmp得差結果等於0,則轉移到指定標號 示例:mov bx,3;cmp bx,3;je s 解釋:將會轉移到s處 jb:若是cmp的差結果小於0,則轉移到指定標號 示例:mov bx,3;cmp bx,4;jb s 解釋:將會轉移到s處 ja:若是cmp的差結果大於0,則轉移到指定標號 示例:mov bx,3;cmp bx,2;ja s 解釋:將會轉移到s處 jnb:若是cmp的差結果不小於0,則轉移到指定標號 示例:mov bx,3;cmp bx,3;jnb s 解釋:將會轉移到s處 jna:若是cmp的差的記過不大於0,則轉移到指定標號 示例:mov bx,3;cmp bx,3;jna s 解釋:將會轉移到s處 循環指令 loop:彙編語言中的循環語句 示例:mov cx,10;loop s 解釋:將s程序段循環執行10次(循環次數由cx的值指定) 過程 call:調用子程序,常與ret成對使用 示例:call s;s:ret 解釋:轉移到子程序,相似於轉移指令,但至關於執行了 push IP jmp near s這兩條指令,記錄了轉移的位置,可使用ret返回此IP的位置 ret:在子程序中同於返回call的指令處,常與call成對使用,而且是近轉移 示例:call s;s:ret 解釋:從子程序跳出,至關於執行了 pop IP,程序執行的下一條語句就是原來call的IP的地址,從而實現了近轉移 retf:在子程序中同於返回call的指令處,常與call成對使用,而且是遠轉移 示例:call s;s:retf 解釋:從子程序跳出,至關於執行了 pop IP pop CS程序執行的下一條語句就是原來call的IP的地址,從而實現了遠轉移 中斷 int:系統中斷 示例:mov ax,4c00h;int 21h 解釋:BIOS和DOS都提供了一些默認的中斷進程,用於持續檢測中斷碼,若是接受到中斷碼,則會在TF=1的狀況下在下一條指令去執行可屏蔽中斷進程,咱們也能夠自定義中斷進程去替代系統的中斷進程。示例中的中斷是去執行21號中斷的ah=4c的子程序,子程序爲退出當前DOS iret:與int配合使用,在子程序中返回,與ret,retf相似
處理機控制指令 cld:設置DF爲0(即正向拷貝) 示例:cld;rep movsb 解釋:設置標誌寄存器DF爲0,即設置拷貝的方向爲正向 std:這是DF爲1(即反向拷貝) 示例:std;rep movsb 解釋:設置標誌寄存器DF爲1,即設置拷貝的方向爲反向 cli:設置TF標誌位爲1 示例:cli 解釋:設置TF爲1後,當接受到可屏蔽中斷時,會在下一條指令執行中斷 sti:設置TF標誌位爲0 示例:sti 解釋:設置TF爲0後,當接受到可屏蔽中斷時,會忽略中斷繼續執行當前程序直至結束 nop:添加一個佔位的一字節數據 示例:funcend:nop 解釋:經常使用來記錄子程序的段結束的位置,好比offset funcend就能夠獲取func結束位置的偏移地址 clc cmc stc hlt wait esc lock
串處理指令 movsb:複製字符串 示例:rep movsb 解釋:能夠正向或反向複製指定爲的字符串到目標地址,參數必須將ds:si源地址、es:di目的地址、cx長度、標誌DF指定,而後調用rep movsb movsw 示例: 解釋: cmps scas lods stos 配合使用: rep repe repne
mov ax,0 能夠用sub ax,ax替代,並且後者2字節,前者3字節 當16進制數,首位數字爲英文,則須要在前面加上0,好比:0A432H 在彙編程序中,mov al,[0]指令與debug程序不一樣,彙編編譯器會將它解釋爲mov al,0 DOS和合法程序都不會使用0:200~0:2ff這段256字節的空間 直接DEBUG顯示的CS就是當前程序段的字節長度 爲何mov 4c00h;int 21h長度爲5字節 暫存數據的時候,通常用棧 bp寄存器默認使用ss做爲段寄存器 沒有寄存器名存在的狀況下指定內存單元的長度:mov word/byte ptr [bx],1 push/pop只對字操做 在10.1節,ret和retf的示例中,在執行命令以前,爲何都要mov bx,0 mul乘法,與div除法原理類似,都分爲8位和16位的計算 16位cpu,有符號溢出範圍79H(127),-80H(128) DF:方向標誌位,與movsb配合使用 adc指令的意義:進行大數的加法或減法 inc和loop不影響cf位 cmp指令只會影響標誌位 CF能說明操做符的大小 SF=1並不能說明運算的結果的正負,由於可能發生溢出 但SF和OF同時能夠說明正負 SF=1,OF=1:(ah)<(bh) SF=1,OF=0:(ah)>(bh) SF=0,OF=1:(ah)<(bh) SF=0,OF=0:(ah)>=(bh) cld和std分別設置DF爲0(正向)和1(反向) Debug中的標誌位對應關係 flag:1--0 OF:OV,NV SF:NG,PL ZF:ZR,NZ PF:PE,PO CF:CY,NC DF:DN,UP loop執行分兩步 cx-- cx不等於0,轉移 中斷過程 取得中斷類型嗎N pushf,將標誌寄存器入棧保存 TF=0,IF=0 push cs push ip (IP)=4*N,(CS)=4*N+2 動態獲取到一段代碼的長度,能夠設置一個nop字節,獲取長度只須要: mov cx,offset do0end-offset do0 do0: mov xx,xxx mov 4c00h int 21h do0end:nop jmp short s佔2字節內存 設置棧頂的ss和sp之間不會響應任何中斷,因此在實驗二的時候,執行mov ss,0後,mov ax,0執行了,只是debug不能將它中斷顯示 通常在中斷例程中還存在子程序,通常經過ah來指定 若是將字符串後的0寫成字符'0',則利用jcxz沒法跳轉 在進行邏輯移位shl或shr時,移位大於1,必須用cl保存位移數,並將最後一次移出的保存到CF中 在CMOS RAM中,端口爲70h(地址端口)和71h(數據端口)存儲時間信息的單元分別爲:秒:0分:2時:4日:7月:8年:9,都佔一個字節 在PC中,外中斷可分爲可屏蔽中斷和不可屏蔽中斷 可屏蔽中斷在IF=1時,cpu會在執行完當前指令後響應中斷,IF=0則不響應此中斷 不可屏蔽中斷是cpu必須響應的中斷,通常不會使用 設置IF:sti,設置IF=1; cli,設置IF=0,IF=0不會執行屏蔽中斷 通碼:按下鍵盤的一個鍵產生的掃描碼;斷碼:鬆開一個鍵產生的掃描碼, 斷碼=通碼+80h 都被送到60h端口 掃描碼一個字節中,通碼的第7位爲0,斷碼第7位爲1 地址標號和數據標號 地址標號,只能在代碼段使用 數據標號,不只表示內存單元的地址,還表示內存單元的長度,與地址標號不一樣是標號後無符號「:」 直接定址表:能夠經過依據數據,直接計算出所要找的元素的位置的表 鍵盤緩衝區的字單元中,高位字節存儲掃描碼,低位字節存儲ASCII碼。 int 16h用於從鍵盤緩衝區讀取字符,ah存儲掃描碼(高位),al存儲字符(低位)