《彙編語言》知識重點總結

《彙編語言》

前言

正式工做以後打算着手作一些逆向方面的研究,聽前輩們的建議,必須先把彙編學會,因而我用第一個月把《彙編語言》(第三版-王爽著)看了一遍,可是人的記憶力是有限的,因此打算以博客的形式再回憶一遍,相信經過這種形式,能讓本身對知識理解的更加模塊化和具體化,也方便本身往後複習,同時也方便了看到這篇博客的同道中人。編程

做用

彙編語言在整個計算機編程語言中的地位能夠說是沒什麼用,不多有人會直接拿彙編語言去寫項目,若是這麼幹的話,不得麻煩死(可是不排除確實有這種需求的時候的作法)。更多時候彙編語言的使用場景是在反編譯別人的二進制代碼以後,對彙編代碼的邏輯還原,而且對於計算機系統總體的理解,我相信沒有什麼比學習彙編語言更快、更好。編程語言

名詞、彙編指令的示例和說明(8086cpu)

  • 寄存器:用於存放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
  • 標誌位:在內存中佔1字節大小,用於運算和程序中的狀態等。經常使用的標誌有ZF,PF,SF,CF,OF,DF
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存儲字符(低位)
相關文章
相關標籤/搜索