這個假期開始系統學習彙編語言,採用跟隨視頻教程的方式,所用教程是網易雲課堂中的《彙編語言從0開始》,講者是workWork。該課程一共有167個課時,每一個課時從幾分鐘到十幾分鐘不等,時間不長,短小精悍,反饋及時,讓人有動力一直看下去。這門課程很適合零基礎的同窗,由於在正式編程前,講者用了大量時間講述基礎性的知識,包括二進制十進制十六進制、CPU執行指令的過程、寄存器的講解、棧的使用等等。我我的認爲,即便你已經不算零基礎了,認真地看完這些課程,鞏固一下基礎知識也是必要的。我以前看過一本基於Linux的教材,由於Linux採用的是AT&T風格,與DOS/Windows的Intel風格有很大差別,因此即便也寫過幾個彙編小程序,但始終以爲對於寄存器、指令/數據長度以及棧的概念懵懵懂懂,基礎並無打好。我建議你們若是是初學者,仍是先從DOS/Windows平臺的彙編開始學習比較好,尤爲是要使用Windows XP中的debug程序反覆練習,這樣能夠在編程以前打好堅實的基礎。
下面對編程以前的基礎知識作一個小小的總結。
1、十進制、二進制和十六進制
二進制之因此重要,是由於整個計算機體系就是創建在二進制的基礎上的,實際上全部的指令和數據在計算機中存儲和運算的形式就是二進制。十六進制之因此重要,是由於查看內存中的指令和數據時,是以十六進制顯示的。一個十六進制數字,實際上至關於四個二進制數字的表示。這方面須要掌握如下幾個知識點:
- 十進制與二進制的相互轉換/快速轉換
- 十進制與十六進制的的相互轉換/快速轉換
- 十六進制與二進制的相互轉換/快速轉換
基礎的相互轉換就不說了,即便對於初學者也應該是容易掌握的。說一下快速轉換的方法。程序員
-
十進制快速轉換成二進制
首先對於二進制來講,位於最末一位的1表示加1,右數第二位表示加2,依次類推爲四、八、1六、3二、64。對於100之內的十進制數,只能是由以上幾個數字相加得成。那麼咱們就能夠開始湊了。好比98,能夠寫成64+32+2,再把對應位置爲1,即1100010。
-
十進制快速轉換成十六進制
這個方法只能用在小於256的數。很簡單,先用該數除以16,獲得一個結果和一個餘數。好比81=5*16+1,則十六進制表示爲51H。
-
十六進制和二進制的快速轉換
上文說過一個十六進制數字能夠由四個二進制數來表示,好比7EH,就是把7用二進制表示,E用二進制表示,即0111 1110。反之亦然,二進制轉換成十六進制時,每四個數字劃分便可。
最後,記住一個式子:
字節byte = 2個十六進制數字 = 8個二進制數字 = 8比特bit
2、CPU、寄存器和指令執行
-
地址信息、數據信息和控制信息
6個小題,掌握了就能夠了。
(1)1個CPU的尋址能力爲8KB,那麼它的地址總線寬度爲 13
8KB = 8*1024字節,總共是2的13次方
(2)1KB的存儲器有 1024 個存儲單元,存儲單元的編號從 0 到 1023
(3)1KB的存儲單元能夠存儲 1024*8 bit,1024 Byte
(4)1GB, 1MB, 1KB 分別是 2^30 2^20 2^10 Byte
(5)地址線有16根,尋址能力爲64KB,20根,1MB,24根,16MB,32根,4GB
(6)數據線有8根,一次能夠傳送數據爲1Byte,16根,2Byte,32根,4Byte
-
寄存器
(1)通用寄存器
ax = ah + al
bx = bh + bl
cx = ch + cl
dx = dh + dl
通常用來存放數據,對於ax來講,能表示最大值爲FFFFH,即0-66535。ax是16位,AH是8位,ah最大可表示FFH,即0-255。對於ax存放的數據是一個字,即兩個字節。而一個地址當中只能存放一個字節,即1個字須要2個地址連續的內存單元存放,高位地址存放高位字節,低位地址存放低位字節
(2)用於表示地址的寄存器
段地址:偏移地址
ds si
es di
ss bp
cs ip
sp
bx
物理地址 = 基礎地址 + 偏移地址
基礎地址 = 段地址 * 16(10H)
其中cs:ip表示讀取指令的地址,ds 是段寄存器,通常以ds:[0]的形式表示要使用的數據所在的地址。
-
指令執行
讀取指令的地址爲cs:ip。
(1)指令執行的過程:
①CPU從cs:ip所組成的地址中讀取指令,將這個指令存放在指令緩存器中;
②ip = ip + 所讀指令的字節數;
③執行指令緩存器中的內容,回到步驟1,重複這個過程。
(2)指令執行要完成的任務:
①數據在什麼位置?
②處理數據;
③把處理事後的結果儲存起來。
3、debug指令
r 顯示寄存器內容
d 顯示內存中的內容
段地址:偏移地址 - 偏移地址
u 將內存中內容翻譯成彙編指令
a 向當前內存中寫指令(彙編指令)
e 加上段地址:偏移地址,即向當前內存中寫入內容(16進制)
4、棧
棧就是一段連續的內存空間,遵循後進先出的準則。棧的操做有兩個,分別是入棧和出棧。棧的地址由ss:sp表示。入棧指令是push加地址,出棧指令是pop加地址。注意push和pop指令後加的地址是待入棧數據的地址/出棧後數據存放的地址。ss:sp永遠指向棧頂數據,能夠由程序員修改決定。注意使用棧時必定要防止越界。
push -> SP - 2 -> SS:SP 字型數據存入
pop -> SS:SP字型數據取出 -> SP - 2
5、基本的彙編指令
-
移動指令
mov 寄存器,數據
mov 寄存器,寄存器
mov 寄存器,內存單元
mov 內存單元,寄存器
mov 段寄存器,寄存器
mov 寄存器,段寄存器
-
運算指令
add 寄存器,數據
add 寄存器,寄存器
add 寄存器,內存單元
add 內存單元,寄存器
sub
-
轉移指令
轉移指令可以修改ip或cs,例如jump 2000:0,實際上就是把cs改爲2000,ip改爲0,那麼下一條指令就是從2000:0開始執行。
6、編程前的總結
-
關於寄存器與地址表示
CS:IP 和指令有關
DS:[0] [1] … 和數據有關
SS:SP 臨時性數據(棧)
-
關於指令執行的過程
經過彙編指令修改CPU中寄存器中的內容。須要考慮的問題有:
(1)數據在哪裏?
(2)數據的長度:字節型數據 字型數據 AX BX CX DX AH AL BH BL
(3)數據的處理 ADD SUB
(4)數據存放到哪裏?
-
關於程序員的工做
數據是咱們程序本身安排,存放在哪裏也要本身安排,指令在哪裏也要本身安排——相比高級語言,彙編語言給程序員絕對的自由,然而自由的代價是謹慎,彙編語言比高級語言更容易出現種種問題。