終於囫圇吞棗的看完王爽老師的《匯編語言》,之所以說囫圇吞棗,是因為現在沒想到要用匯編做些什么,而且覺得匯編目前對我來說,只是一門讓我們更好的了解底層的語言,用它來寫程序,拋開效率問題,遠沒有C來得舒服。現在還沒達到追求效率的水平,所以就先大概了解一下匯編吧。如果以后要用到匯編碼字的話,再深入學習吧。接下來匯編的話,就堅持每天看看51的一些例程吧。。。
第一章 基礎知識
一.機器碼:1.計算機只認識0,1兩種狀態。而機器碼只能由0,1組成。故機器碼相當難認,故產生了匯編語言。
2.其中匯編由三類指令形成:匯編指令(有機器碼對應),偽指令,其他符號(編譯的時候有用)。
每一總CPU都有自己的指令集;注意學習的側重點。
二.存儲器:1.存儲單元中數據和指令沒任何差別。
2.存儲單元:Eg:128個儲存單元(0~127)128byte。//1字節=1B=1byte=8bit 條件反射:1存儲單元=1B=8個2進制
;以后的ax,cs之類的占兩個存儲單元,ah之類的占一個
3.CPU對存儲器的讀寫:地址信息+控制信息+數據信息
三.總線: 1.地址總線:尋址用,參數(寬度)為N根,則可以尋到2^N個內存單元。//因為一根總線只能表示0,1,N根的話可以表示2^N
2.數據總線:傳送數據用,參數為N根,一次可以傳送N/8個存儲單元。
3.控制總線:cpu對元器件的控制能力。越多控制力越強。
四.內存地址空間:1.由地址總線決定大小。
2.主板:cpu和核心器件(或接口卡)用地址總線,數據總線,控制總線連接起來。
3.接口卡:由於cpu不能直接控制外設,需通過接口卡間接控制。
4.各類存儲器芯片:RAM,BIOS(主板,各芯片)的ROM,接卡槽的RAM
CPU在操控他們的時候,把他們都當作內存來對待,把他們總的看作一個由若干個存儲單元組成的邏輯存儲器,即我們所說的內存地址空間。
;自己的一點理解:CPU對內存的操作是一樣的,但是在cpu,內存,芯片之間的硬件本身所牽扯的線是不同的。所以一些地址的功能是對應一些芯片的。
;待總結
第二章 寄存器
引入:CPU中含有運算器,寄存器,控制器(由內部總線連接)。而寄存器是可以用來指令讀寫的部件。8086有14個寄存器(都是16位,2個存儲空間)。
一.通用寄存器(ax,bx,cx,dx),16位,可以分為高低位
注意1.范圍:16位的2^16-1,8位的2^8-1
2.進行數據傳送或運算時要注意位數對應,否則會報錯
二.字:1. 1個字==2個字節。
2. 在寄存器中的存儲:0x高位字節低位字節 ;單元認定的是低單元
數制,16進制h,2進制b
三.20根數據總線的16位cpu--8086給出物理地址的方法:
1.20根數據總線(稍外):尋址能力為1M
2.16位的cpu(內部):一次能處理的數據位2^16。
3.方法:物理地址=段地址*16+偏移地址 ;*16==左移四位
四.段: 1.段地址為16的倍數
2.一個段的長度最長為64K;因為偏移地址為16位,尋址能力為64K
五.回到寄存器--段寄存器(cs,ds,ss,es)
1.cs(代碼段寄存器),ip(指針指令寄存器);cs為存放指令的段地址
2.cpu中cs,p的運作過程:先將兩個16位的數通過地址加法器變成一個20位的地址,通過輸入輸出控制電路,尋址並返回給cpu指令。ip自動增加。執行指令。next。。。
3.修改cs;ip:mov不行,jmp行。形為:jmp cs:ip 或者jmp ip(通用寄存器);轉移指令修改ip
六.代碼段:
1.要小於64K
2.存放后用cs,ip指向第一條指令的首地址。
;待總結
第三章 還是寄存器
一.內存中字的存儲:因為字(2個存儲單位)要存在兩個字節當中。運用mov 等指令時,指向的是低字節。
二.DS和[address]
1.[]中放的是偏移地址,默認段地址是ds。
2.段地址的移入:要通過通用寄存器。
三.mov add sub(減) 指令
除了處理[]內存可以位數可以不對應,其他都要。
四.數據段
五.棧
1.概念:FILO,以字為單位。
2.棧頂的單元為低,棧底的單元較高。
3.ss(段寄存器):sp(寄存器):任意時刻指向棧頂。
4.push進棧:sp-2 mov;pop出棧:,mov sp+2 5.棧的最大容量為64K,超出覆蓋
注意初始化的時候棧頂的指向是棧底+1。入出棧最易出錯
;未完待續
第四章 第一個程序
一.源程序的架構:
開頭:assume(假設)cs: xxx
中間:xxx segment(段)
…………
程序返回:mov ax,4c00h
int 21h
xxx ends
結束:end
二.從碼字到.exew
下載masm,運行cmd,找到目錄,masm 文件名,link 文件名,文件名
。
第五章 [bx]和loop
一.[bx]
1.Q:為什么是bx,ax,cx,dx行不行? A:不行
用debug 的a指令試試看。(參考實驗一)
可以理解為bx特有的功能,和后面與loop配套使用的cx一樣。
二.loop指令
1.與ax對應使用,當cx不為0時,一直循環。在loop指令前,一定要把循環次數mov進cx。在循環里面,執行完會sub cx,1,再判斷ax是否為0,執行跳出或者循環。
三.loop和[bx]聯合使用
1.通過改變bx值可以操作連續的一段空間。
第六章 包含多個段的函數
引入:
使用一:在代碼段中使用數據
1.先將數據儲存到一段連續的內存空間中(由系統分配),用loop和[]來讀寫這些數據。
2.start:跳過數據存儲的地方,指令開始的地方。
使用二:在代碼段中使用
1.先dw要用的空間,棧空是sp 為dw的個數*2-2;
正文:將數據、代碼、棧放入不同的段中
assume cs:code,ds:data,ss:stack ;先聯系起來
data segment
dw
data end
stack segment
dw
stack end
code segment
mov ax,stack
mov ss,stack
mov sp,ffh ;棧地址放到棧段
mov ax,data
mov ds,ax ;數據地址放到數據段
;核心程序
;核心程序
code end
end
第七章 更加靈活的定位內存地址的方法
引入:
1.add 和 or:操作對象是位(bit)。
2.關於ASCII碼:占一個字節(byte)
3.以字符給出數據 ‘xxx' 每一個x占一個字節。在程序時可直接看成一個或一排連續的ASCII碼。
4.綜合使用:大小寫互換。
正文:
1.[bx+idata]:偏移地址為(bx)+idata ;疑問:為什么不是((bx)+idata )自己理解:可能是bx是一個寄存器,其中的值用()表示,
;這樣已經完成了寄存器到數值的轉換了
[bx]:偏移地址為(bx)
用idata[bx]進行數值的應用
2.si和di:si和di是和bx相似的8位寄存器。
;bx被占領使用時應該考慮到這個。
3.[bx+si+idata]各種組合都是行的
第八章 數據處理的兩個基本問題
一.處理的數據在什么地方?
機器指令處理的數據在什么地方?
內存,CPU,指令緩沖器
匯編語言中數據位置的表達。
內存([]),CPU(ax),指令緩沖器(1)
尋址: 直接尋址 ;EA=idata
寄存器間接尋址 ;EA=(ax)
寄存器相對尋址 ;EA=(ax)+idata
基址變址尋址 ;EA=(ax)+(si)
相對基址變址尋址 ;EA=(ax)+(si)+idata
;原來 di 對應的是ds;si對應的是ss。
二.指令要處理的數據有多長?
ax之類的兩個字節,al之類的一個字節
在沒有匯編的情況下,用操作符X ptr 指明內存單元中的長度,X在匯編中可以為byte或word。
三.div指令
dd偽指令
dup
第九章 轉移指令的原理
一.操作符offset:編譯時標號處取偏移地址用
二.jmp指令
1.根據位移進行轉移的jmp指令 jmp short 標號 ;功能是IP=IP+8位位移
2.轉移的目的地址在指令中的jmp指令 jmp far 標號;可以同時修改CS,IP
3.轉移地址在寄存器的jmp指令:jmp 16位reg 功能:(ip)=(reg)
4.轉移地址在內存中的jmp指令:
jmp word ptr 內存單元地址(段內轉移) ;(ip)=(內存單元地址)
jmp dword ptr 內存單元地址(段間轉移) ;(ip)=(內存單元地址)(cs)=(內存單元地址+2)
三.jcxz 指令
當cx不為0時,跳轉到jcxz 標號位置。if((cx)==0)jmp short 標號
第十章 CALL和RET指令
一.ret(近轉移):pop ip
retf(遠轉移):pop ip
pop cs
使用前要先進棧。retff的先push cs再push ip
二.call指令
ip進棧保存,改動ip跳轉,執行 ;注意進棧時地ip是call之后的一條
1.call 標號是 相當於進行:push ip ;根據位移(段內轉移)
jmp near ptr 標號
2.call far ptr 標號 相當於進行:push cs ;段間轉移
push ip
jmp far ptr 標號
3.call 16位reg 相當於進行:push ip
jmp reg
4.call word ptr 內存單元地址
call dword ptr 內存單元地址
三.call和ret配合使用
call 是進棧 調用后 用ret返回
四.mul指令
mov 8位reg或者內存字節單元中;另一個乘數默認放在al,其中結果放在ax中。
mov 16位reg或者內存字單元中;另一個乘數默認放在ax,其中結果高位在dx,低位在ax
五.模塊化設計程序
1.參數和結果的傳遞(通過寄存器)
2.多個數據的傳遞(在字符串中在內存中的首地址放到寄存器)
3.寄存器沖突問題:在子函數中進去前把寄存器進棧,返回主函數時在出棧(注意順序)
第十一章 標志寄存器
標志寄存器的作用:1.用來儲存相關的某些指令的執行結果;
2.用來為CPU執行相關指令提供行為依據
3.用來控制CPU的相關工作模式
其他寄存器合起來存放數據的,而標志寄存器是按位起作用的。
一.ZF標志 Z for 零;結果不為0 他為0
二.PF標志 P for 奇偶;1的個數為奇 他為0
三.SF標志 S for 負;結果為非負 他為0
四.CF標志 C for 無符號溢出;沒溢出 他為0
五.OF標志 O for out;
六.adc指令(帶進位加法指令)
adc 操作對象1,操作對象2
功能:操作對象1=操作對象1+操作對象2+CF ;比add多加了個CF
作用:
七.sbb指令:(帶借位減法指令)
sbb 操作對象1,操作對象2
功能:操作對象1=操作對象1-操作對象2-CF ;比sub多加了個CF
八.cmp指令(對上述各種標志位的應用):
cmp 操作對象1,操作對象2
功能:相當於sub指令,只是不保存運算完之后的結果,只是影響標志寄存器的各位()
九.檢測比較結果的條件轉移指令 jcxz
轉移是修改IP
條件是滿足一定條件才執行轉移指令
檢測是什么呢?
第十二章 內中段
一.內中斷的產生
中斷類型碼為一個字節,可以表示256種中斷信息的來源。
中斷處理程序。;cpu的設計者必須在中斷信息和其處理程序的入口地址之間建立某種聯系。
中斷向量表
cpu用8位的中斷類型碼通過中斷向量表找到相應的中斷處理函數的入口。
中斷向量表是存放着中斷處理程序入口地址的列表。
一個表項存放一個中斷向量,也就是一個中斷處理函數的入口地址,所以一個表項占兩個字節。高字節存放段地址,低字節存放偏移地址。
二.中斷過程
1.取得中斷類型碼N
2.pushf
3.TF=0 IF=0
4.push CS
5.push IP
6.(IP)=(4*N),(CS)=(4*N)+2
三.中斷處理程序和iret
1.保存用到的寄存器
2.處理程序
3.恢復用到的寄存器
4.用iret指令返回
四.除法錯誤中斷(o號中斷)的處理
;當除法溢出的時候,產生中斷信息
編寫中斷處理程序d0
可以將do0傳送到內存0000:0200(之后的256字節為空)
將do0的入口地址0000:0200存儲在中斷向量表0號中
五.安裝
中斷被執行的過程:先將中段處理程序加載到內存當中,然后再復制到內存單元為0:200的地址當中,最后最在中斷向量表0號中填入do0的入口中地址0:200
具體編程:
1.設置ds,si指向源地址:mov ax,cs
mov ds,ax
mov si,offset do0
2.設置es,di指向目的地址: mov ax,0
mov es,ax
mov di,200h
3.設置cx為傳輸長度:mov cx,offset do0end-offset do0
4.設置傳輸方為正:cld
5.確定信息:rep movsb
如果中斷中有數據要處理的話,可以存放到do0函數中,用jmp跳轉到do0start,數據在jmp之后的內存位置中,確保不被用到。
六.設置中斷向量
mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0
第十三章 int指令
一.int 指令
功能是能引發中斷
取中斷類型碼n
標志寄存器入棧:IF=0,TF=0
CS,IP入棧
(IP)=(n*4) (CS)=(n*4+2)
二.編寫供應用程序調用的中斷例程
int和iret的使用類似於call和ret
三.對in,iret和棧的深入理解
暫時不了解
四.BIOS和DOS所提供的中斷例程
第十四章 端口
。。。
第十五章 外中斷
PC機鍵盤的處理過程
鍵盤的輸入
60h端口
a的通碼/掃描碼:1e 斷碼=通碼+80h
引發9號中斷
若IF=1,響應中斷
執行int9中斷例程
讀出60h端口中的掃描碼
如是字符型的將掃描碼和對應的ASCII碼送入內存中的BIOS鍵盤緩沖區
如果是控制鍵或切換鍵,則將其轉換為狀態字節寫入內存中存儲狀態字節的單元
編寫int9中斷例程
鍵盤輸入的處理過程:鍵盤產生掃描碼--掃描碼送入60h端口--引發9號中斷--CPU執行int9中斷例程處理鍵盤輸入
從端口60h讀出鍵盤的輸入 in al,60h
調用BIOS的int9中斷例程
要先將原來的存放中斷入口地址的單元儲存在另外的空間中
push es:[9*4]
pop ds:[0]
push es:[9*4+2]
pop ds:[2]
在中斷向量表中設置新的int9中斷入口程序的地址
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs
新的中斷程序中要
相關寄存器進棧
讀端口 in al,60h
對int指令進行模擬,調用原來的int9中斷例程
