這兩天花了點時間學習了一下彙編語言,用的是 王爽老師著的彙編語言(第三版),整個學習是基於8086/88 CPU 16 位微機,在此作一下總結,若有錯誤,歡迎指正。oop
1、寄存器學習
8086/88 CPU 中共有 14 個16位寄存器,AX, BX, CX, DX, SI, DI, SP, BP, IP, CS, SS, DS, ES, PSWui
其中 通用數據寄存器 有 AX, BX, CX, DX。 可分爲8 個 8 位寄存器 AH, BH, CH, DH (高八位)和 AL, BL, CL, DL(低八位)。指針
通用地址寄存器 有 BP, SP, SI, DI 內存
段寄存器 有 CS, DS, ES, SSit
指令指針寄存器 有 IP編譯
標誌寄存器 PSW (程序狀態字)循環
由於8086 CPU 有20 位地址總線,能夠傳送 20 位地址,達到 1MB 的尋址能力,但8086CPU 又是 16 位結構,沒法一次發出 20位地址,因此就由兩個16 位地址合成 20位地址,這兩個16 位地址一個稱爲段地址, 一個稱爲偏移地址,經過地址加法器進行合成 物理地址。二進制
物理地址 = 段地址(SA) * 16 + 偏移地址(EA)請求
在內存中數據和指令都是由二進制構成,那麼CPU 怎麼判斷該數據是指令仍是數據呢?這就要看由什麼寄存器指向該地址,數據寄存器指向的是數據,指令寄存器指向的是指令
不可直接修改CS 或 IP 的值
接下來,對於每個寄存器,單獨拿出來講說
AX : AH AL 累加器
eg: mov ax,0001h
mov ds,ax
add ax,ax
BX :BH BL 基址寄存器
eg: mov ax,[bx] 等價於 (ax) = ((ds)*16 + (bx))
inc bx bx 中的內容加一
CX : CH CL 計數器
eg: mov cx,12
s:add ax,ax
loop s 循環執行標記 s, 首先 (cx) = (cx)-1, 再判斷 cx 中的值,若是cx 不爲 0,則轉到s 所標識的地址處執行,不然則執行下一條指令
DX : DH DL 數據寄存器,和AX 相似
BP : 基址指針,主要用於存放地址和基址(默認相對與ss 段)
SP : 棧頂指針,與ss 段寄存器配合,共同指向棧頂地址元素
DI : 目的變址寄存器,相似於 BX, 但不能夠分爲高八位和低八位
SI : 源變址寄存器,和DI 相似
下面三組實現了相同的功能:
(1) mov bx,0
mov ax,[bx]
mov ax,[bx+123]
(2) mov si,0
mov ax,[si]
mov ax,[si+123]
(3) mov di,0
mov ax,[di]
mov ax,[di+123]
CS : 代碼段寄存器, 指示了CPU 當前要讀取的指令的地址,在任意時刻,CPU 將CS:IP 指向的內容當作指令來執行, 與IP 指令指針寄存器配合使用
DS : 數據段寄存器, 一般用於存放要訪問的數據的段地址,
eg: mov bx,1000h
mov ds,bx
mov al,[0] 將10000H(1000h:0)中的數據讀到 al 中, ds:[0]
ES : 附加數據段寄存器, 對於DS 的一個附加
SS : 堆棧數據段寄存器,任意時刻,ss: sp 指向的是棧頂的元素,ss: [0] 指向的是棧段的開始地址
eg: mov ax,1000h
mov ss,ax 設置棧的段地址
mov sp,0010h 設置棧頂的偏移地址
IP : 指令指針寄存器,與CS 寄存器配合,指向CPU 當前要讀取的指令的地址
PSW: 標誌寄存器,也稱爲狀態轉移字,決定是否跳轉,有三個控制標誌(IF, DF, TF), 六個狀態標誌(SF, PF, ZF, OF, CF, AF)
IF : 中斷容許標誌,控制CPU 是否響應可屏蔽中斷請求,IF = 1 能響應,IF = 0 不能響應
DF : 方向標誌,控制串操做時源串和目的串的變址方向, DF = 1 向減的方向,DF = 0 向加的方向
TF : 陷阱標誌(單步中斷標誌),TF = 1 執行當前指令後暫停,TF = 0 執行當前指令後不會暫停
SF : 符號標誌,指令執行結果的最高二進制是0 仍是 1,爲0,則SF = 0,表明正數,爲 1,則SF = 1,表明負數
PF : 奇偶校驗標誌,指令執行結果中低八位中 1 的個數是奇數個仍是偶數個,若爲奇數個則 PF = 0,若爲偶數個則 PF = 1
ZF : 零標誌,指令執行的結果是否是 0, 若爲 0,則 ZF= 1,不然 ZF = 0
OF : 溢出標誌, 有符號數的溢出標誌,執行指令的結果是否超出有符號數的表示範圍,超出則OF = 1,不然OF = 0
正加正得負,正減負得負,負加負得正,負減正得正,若出現則OF = 1, 不然OF = 0
CF : 進位/錯位標誌,無符號數的溢出標誌,指令執行結果的最高位是否有向更高位進位或者錯位,
如有則CF = 1, 同時也表明無符號數溢出,若無則CF = 0,也表明無符號數未溢出
AF : 輔助進位/錯位標誌,低四位二進制是否是有向高位進位或錯位,如有則AF = 1,不然AF = 0,其主要用於BCD 修正運算
eg:
(1) 58H + 3CH = 94H SF = 1, PF = 0, ZF = 0, OF = 1, CF = 1, AF = 1
(2) 0039H - FCE8H = 0351HDW SF = 0, PF = 0, ZF = 0, OF = 0, CF = 1, AF = 0
(3) 35H + CBH = 00H SF = 0, PF = 1, ZF = 1, OF = 0, CF = 1, AF = 1
在DEBUG 中,查詢PSW, 對應的標誌寄存器狀態
標誌 1 0
OF OV NV
SF NG PL
ZF ZR NZ
PF PE PO
CF CY NC
DF DN UP
IF EI DI
AF AC NA
2、DEBUG
A(Assemble) 逐行彙編
C(Compare) 比較兩內存塊
D(Dump) 內存 16 進制顯示
E(Enter) 修改內存字節
F(fin) 預置一段內存
G(Go) 執行程序
H(Hexavithmetic) 制算術運算
I(Input) 從指定端口地址輸入
L(Load) 讀盤
M(Move) 內存塊傳送
N(Name) 置文件名
O(Output) 從指定端口地址輸出
Q(Quit) 結束
R(Register) 顯示和修改寄存器
S(Search) 查找字節串
T(Trace) 跟蹤執行
U(Unassemble) 反彙編
W(Write) 存盤
就一些較爲經常使用的命令進行詳細的說明
-A[address] 該命令容許鍵入彙編語言語句,並把他們彙編成機器代碼,相繼的存儲在從指定地址開始的存儲區中。
DEBUG 把鍵入的數字都當作十六進制,因此要鍵入十進制數,則要在其後面加以說明,如100D
-D[address] 或 -D[range] 顯示存儲單元內容,若是沒有制定段地址,自動顯示DS 段的內容,若是隻指定首地址,則顯示從首地址開始的80 個字節的內容,若是徹底沒有指定地址,則顯示上一個D 命令顯示的最後一個單元后的內容
-E address [list] 或 -E address 該命令用以修改存儲單元的內容
第一種是用給定的內容來代替指定範圍內的存儲單元內容
第二種是逐個單元相繼修改的方法,再按空格後修改下一個單元的內容
-G[=address1][address2][address3...> 運行命令,其中address1 指定了運行的起始地址,如不指定則從當前的CS:IP 開始運行,後面的地址均爲斷點地址,當執行到斷點時,就暫停執行並顯示當前全部寄存器及標誌位的內容,和下一條要執行的指令
-Q 退出DEBUG,返回DOS,該命令沒有存盤功能,如需存盤應先使用W 命令
-R 或 -R range name 或 -RF 查看/修改寄存器
第一種是顯示CPU 內全部寄存器內容和標誌位狀態,
第二種是顯示和修改某個寄存器的內容,即顯示寄存器 的內容,如不需修改則鍵入Enter, 不然鍵入欲修改的內容
eg:-R BX
BX 0369
:059F
第三種是顯示和修改標誌位的內容,如不需修改則鍵入Enter, 不然鍵入欲修改的內容
eg:-RF
OV NG ZR PE CY DN EI AC -PONZUP
-T[=address] 或 -T[=address][value] 跟蹤命令
第一種是逐條指令跟蹤,從指定地址執行一條指令後停下來,顯示全部寄存器內容和標誌位的值,若是沒有指定地址,則從當前的CS:IP開始執行
第二種是多條指令跟蹤,從指定地址執行n 條指令後停下來,n 由 value 指定
-U[address] 或 -U[range] 反彙編命令
第一種是從指定地址開始,反彙編 32 個字節,若是地址被省略,則從上一個 U 命令的最後一條指令的下一個單元開始顯示 32 個字節
eg:-U100
第二種是對指定範圍內的存儲單元進行反編譯,
eg:-U100 112 或 -U100 10c
// 待更