• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            無我

            讓內(nèi)心永遠(yuǎn)燃燒著偉大的光明的精神之火!
            靈活的思考,嚴(yán)謹(jǐn)?shù)膶?shí)現(xiàn)
            豪邁的氣魄、頑強(qiáng)的意志和周全的思考

            匯編語言學(xué)習(xí)筆記

            從今天開始,用心學(xué)習(xí)王爽的《匯編語言》!
            扎扎實(shí)實(shí),勿在浮沙建高樓!

              —————2012.5.29 21:30

             

            第1章 基礎(chǔ)知識(shí)
            以后用到的知識(shí),以后再說。
            匯編課程的研究重點(diǎn)放在如何利用硬件系統(tǒng)的編程結(jié)構(gòu)和指令集有效靈活地控制系統(tǒng)進(jìn)行工作。
            每一種微處理器,由于硬件設(shè)計(jì)和內(nèi)部結(jié)構(gòu)的不同,就需要用不同的電平脈沖來控制,使他工作。所以每一種微處理器都有自己的機(jī)器指令集,也就是機(jī)器語言。

            匯編語言由以下3類指令組成:
            匯編指令:機(jī)器碼的助記符,有對(duì)應(yīng)的機(jī)器碼。
            偽指令:沒有對(duì)應(yīng)的機(jī)器碼,由編譯器執(zhí)行,計(jì)算機(jī)并不執(zhí)行。
            其他符號(hào):如:+、-、*、%等,由編譯器識(shí)別,沒有對(duì)應(yīng)的機(jī)器碼。
            匯編語言的核心是匯編指令,它決定了匯編語言的特性。

            要靈活地利用匯編語言編程,首先要了解CPU是如何從內(nèi)存中讀取信息,以及向內(nèi)存中寫入信息的。
            總線:
            根據(jù)傳送信息的不同,總線從邏輯上又分為3類,即地址總線、控制總線和數(shù)據(jù)總線。
            地址總線:
            CPU是通過地址總線來指定存儲(chǔ)器單元的。地址總線上能傳送多少個(gè)不同的信息,CPU就可以對(duì)多少個(gè)存儲(chǔ)單元進(jìn)行尋址。
            所以32位機(jī)器,地址總線有32根,能尋址2^32=4G空間。
            數(shù)據(jù)總線:
            CPU與內(nèi)存或其他器件之間的數(shù)據(jù)傳送是通過數(shù)據(jù)總線來進(jìn)行的。數(shù)據(jù)總線的寬度決定了CPU和外界的數(shù)據(jù)傳送速度。
            32位的數(shù)據(jù)總線一次能傳送4個(gè)字節(jié)的數(shù)據(jù)。
            控制總線:
            CPU對(duì)外部器件的控制是通過控制總線來進(jìn)行的。在這里控制總線是個(gè)總稱,控制總線是一些不同控制線的集合。有多少根控制總線,就意味這CPU提供了對(duì)外部器件的多少種控制。所以,控制總線的寬度決定了CPU對(duì)外部器件的控制能力。
            內(nèi)存地址空間
            最終運(yùn)行程序的是CPU,我們用匯編編程的時(shí)候,必須要從CPU角度考慮問題。對(duì)CPU來講,系統(tǒng)中的所有存儲(chǔ)器中的存儲(chǔ)單元都處于一個(gè)統(tǒng)一的邏輯存儲(chǔ)器中,他的容量受CPU尋址能力的限制。這個(gè)邏輯存儲(chǔ)器即是我們所說的內(nèi)存地址空間。
            那么,80386PC的內(nèi)存地址空間是如何分布的呢?


            第2章 寄存器(CPU工作原理)
            一、寄存器分類:
            數(shù)據(jù)寄存器:AX、BX、CX、DX四個(gè)寄存器
            指針寄存器:SP堆棧指針、BP基址指針
            變址寄存器:SI源地址、DI目的地址
            段寄存器:CS代碼段、DS數(shù)據(jù)段、SS堆棧段、ES附加段
            控制寄存器:IP指令指針寄存器、FLAG標(biāo)志寄存器
            數(shù)據(jù)寄存器,指針寄存器和變址寄存器統(tǒng)稱為通用寄存器。這樣稱呼的理由是,這些寄存器除了各自規(guī)定的專門用途外,他們均可用于傳送和暫存數(shù)據(jù),可以保存算術(shù)邏輯運(yùn)算中的操作數(shù)和運(yùn)算結(jié)果。

            二、寄存器訪問規(guī)則:
            1、兩個(gè)操作對(duì)象的位數(shù)應(yīng)當(dāng)是一致的。
            2、8086CPU不支持直接將數(shù)據(jù)送入段寄存器的操作。
            3、只有mov、push、pop指令能對(duì)段寄存器進(jìn)行操作。
            4、8086CPU的入棧和出棧操作都是以字為單位進(jìn)行的。
            5、在8086CPU中,只有bx,si,di,bp這4個(gè)寄存器可以用在[]中來進(jìn)行內(nèi)存單元的尋址。
            6、在[]中,這4個(gè)寄存器可以單個(gè)出現(xiàn),或只能以4種組合出現(xiàn):bx和si、bx和di、bp和si、bp和di。
            7、只要在[]中使用寄存器bp,而指令中沒有顯性的給出段地址,段地址就默認(rèn)在ss中。


            一個(gè)典型的CPU由運(yùn)算器、控制器、寄存器等器件構(gòu)成,這些器件靠?jī)?nèi)部總線相連。

            8086的所有寄存器都是16位的,可以存放兩個(gè)字節(jié)。
            16位結(jié)構(gòu)描述了一個(gè)CPU具有下面幾方面的結(jié)構(gòu)特性:
            1、運(yùn)算器一次最多可以處理16位的數(shù)據(jù)。
            2、寄存器的最大寬度為16位。
            3、寄存器和運(yùn)算器之間的通路為16位。
            8086有20位地址總線,與CPU內(nèi)部結(jié)構(gòu)的16位不同。
            采用一種在內(nèi)部使用兩個(gè)16位地址合成的方法來形成一個(gè)20位的物理地址。
            物理地址=段地址*16 + 偏移地址
            尋址模式的本質(zhì)含義是:CPU在訪問內(nèi)存時(shí),用一個(gè)基礎(chǔ)地址和一個(gè)相對(duì)于基礎(chǔ)地址的偏移地址相加,給出內(nèi)存單元的物理地址。
            所以,也可由此看出系統(tǒng)的CPU結(jié)構(gòu)、地址總線、數(shù)據(jù)總線和控制總線寬度是不一定相同的。
            提問:386之后的機(jī)器呢?

            回答:

            8080處理器擁有16位地址總線和8位數(shù)據(jù)總線;
            8086內(nèi)、外部數(shù)據(jù)總線均為16位,地址總線為20位;
            80286內(nèi)部和外部數(shù)據(jù)總線皆為16位,地址總線為24位;
            80386,80486的內(nèi)部和外部數(shù)據(jù)總線都是32位,地址總線也是32位;
            Pentium是64位數(shù)據(jù)總線,32位地址總線;
            Pentium Pro是64位數(shù)據(jù)總線,地址總線就已經(jīng)上升為36根了。
            具體可見下圖,來自于《80x86匯編語言程序設(shè)計(jì)》:

             

            段的概念:內(nèi)存并沒有分段,段的劃分來自于CPU。在編程時(shí)根據(jù)需要,將若干地址連續(xù)的內(nèi)存單元看做一個(gè)段,用段地址*16定位段的起始地址(基礎(chǔ)地址),用偏移地址定位段中的內(nèi)存單元。

            在8086CPU加電啟動(dòng)或復(fù)位后,CS和IP被設(shè)置為CS=FFFFH,IP=0000H,即在8086PC機(jī)剛啟動(dòng)時(shí),CPU從內(nèi)存FFFF0H單元中讀取指令執(zhí)行,F(xiàn)FFF0單元中的指令是8086PC機(jī)開機(jī)后執(zhí)行的第一條指令。

             
            第3章實(shí)驗(yàn)2最后一題的猜測(cè):
            在網(wǎng)上看到別人的答案都是說,由于把此處的位置當(dāng)做棧了,而t產(chǎn)生中斷,所以就將 標(biāo)識(shí)寄存器、CS、IP入棧保存。不過我發(fā)現(xiàn)除了以上之外,還總是保存了另外兩個(gè)寄存器的內(nèi)容,其順序分別是:
            ax,bp,ip,cs,eflags
            ----不知道為什么總是還保存了bp和ax。

            DOS方式下,一般情況下,0:200~0:2ff空間中沒有系統(tǒng)或其他程序的數(shù)據(jù)和代碼;這是一段安全的空間!其實(shí)這屬于中斷向量表的空間,只是一般這一段的中斷向量表項(xiàng)都是空的。

            DOS加載exe:
            1、程序加載后,ds中存放著程序所在內(nèi)存區(qū)的段地址,這個(gè)內(nèi)存區(qū)的偏移地址為0,則程序所在的內(nèi)存區(qū)的地址為ds:0.
            2、這個(gè)內(nèi)存區(qū)的前256個(gè)字節(jié)中存放的是PSP,DOS用來和程序進(jìn)行通信。從256(100H)字節(jié)處向后的空間存放的是程序。
            3、CX寄存器存放的程序的長(zhǎng)度。
            即是:從ds中可以得到PSP的段地址SA,PSP的偏移地址為0,則物理地址為SA*16+0.
            程序的物理地址為SA*16+0+256=SA*16+16*16+0=(SA+16)*16+0=SA+10H:0

             

            第7章 更靈活的定位內(nèi)存地址的方法

            “如果一個(gè)問題的解決方案,使我們陷入一種矛盾之中。那么,很可能是我們考慮問題的出發(fā)點(diǎn)有了問題,或是說,我們起初運(yùn)用的規(guī)律并不合適。”這段話包含很深刻的道理,不僅僅適用于計(jì)算機(jī)問題,技術(shù)問題,同樣適用于生活中,人生上所有的問題。

            更靈活的方式來指明內(nèi)存單元:[bx+idata].寫法:
            mov ax,[bx+200]
            mov ax,[200+bx]
            mov ax,200[bx]
            mov ax,[bx].200

            si、di是兩個(gè)和bx功能類似的寄存器,但是這兩個(gè)不能拆分成兩個(gè)8位寄存器。
            [bx+si] ~ [bx+di] ~ [bx][si] ~ [bx][di]
            [bx+si+idata] ~ [bx+di+idata]
            mov ax,[bx+si+200]
            mov ax,[bx+200+si]
            mov ax,[200+bx+si]
            mov ax,200[bx][si]
            mov ax,[bx].200[si]
            mov ax,[bx][si].200
            本章結(jié)束語:
            “下一章中,我們將對(duì)尋址方式的問題進(jìn)行更深入地探討。之所以如此重視這個(gè)問題,是因?yàn)閷ぶ贩绞降倪m當(dāng)應(yīng)用,使我們可以以更合理的結(jié)構(gòu)來看待所要處理的數(shù)據(jù)。而為所要處理的看似雜亂的數(shù)據(jù)設(shè)計(jì)一種清晰的數(shù)據(jù)結(jié)構(gòu)是程序設(shè)計(jì)的一個(gè)關(guān)鍵問題。”

             

            第8章 數(shù)據(jù)處理的兩個(gè)基本問題
            計(jì)算機(jī)是進(jìn)行數(shù)據(jù)處理、運(yùn)算的機(jī)器,那么有兩個(gè)基本的問題就包含在其中:
            1、處理的數(shù)據(jù)在什么地方?
            2、要處理的數(shù)據(jù)有多長(zhǎng)?
            匯編語言中用3個(gè)概念來表達(dá)數(shù)據(jù)的位置:
            1、立即數(shù):執(zhí)行前在CPU的指令緩沖器中,在匯編指令中直接給出。
            2、寄存器:指令要處理的數(shù)據(jù)在寄存器中,在匯編指令中給出相應(yīng)的寄存器名。
            3、段地址(SA)和偏移地址(EA):指令要處理的數(shù)據(jù)在內(nèi)存中,在匯編指令中可用[x]的格式給出EA,SA在某個(gè)段寄存器中。
            當(dāng)數(shù)據(jù)存放在內(nèi)存中的時(shí)候,我們可以用多種方式來給定這個(gè)內(nèi)存單元的偏移地址,這種定位內(nèi)存單元的方法一般被稱為尋址方式。尋址方式參見8.4節(jié)的尋址方式表。

            匯編語言用以下方法處理數(shù)據(jù)長(zhǎng)度的問題:
            1、通過寄存器名指明要處理的數(shù)據(jù)的尺寸。
            2、在沒有寄存器名存在的情況下,用操作符X ptr指明內(nèi)存單元的長(zhǎng)度,X在匯編指令中可以為word或byte。
            3、其他方法:有些指令默認(rèn)了訪問的是字單元還是字節(jié)單元,比如,push、pop指令只進(jìn)行字操作。

            div指令:除法指令,使用div做除法的時(shí)候應(yīng)注意以下問題:
            1、除數(shù):有8位和16位兩種,在一個(gè)reg或內(nèi)存單元中。
            2、被除數(shù):默認(rèn)放在AX或DX和AX中,如果除數(shù)為8位,被除數(shù)則為16位,默認(rèn)在AX中存放;如果除數(shù)為16位,被除數(shù)則為32位,在DX和AX中存放,DX存放高16位,AX存放低16位。
            3、結(jié)果:如果除數(shù)為8位,則AL存儲(chǔ)除法操作的商,AH存儲(chǔ)除法操作的余數(shù);如果除數(shù)為16位,則AX存儲(chǔ)除法操作的商,DX存儲(chǔ)除法操作的余數(shù)。

             

            第9章 轉(zhuǎn)移指令的原理
            可以修改IP,或同時(shí)修改CS和IP的指令統(tǒng)稱為轉(zhuǎn)移指令。
            8086CPU的轉(zhuǎn)移指令分為以下幾類:
            1、無條件轉(zhuǎn)移指令(如jmp)。
            2、條件轉(zhuǎn)移指令
            3、循環(huán)指令(如loop)。
            4、過程
            5、中斷

            offset操作符在匯編語言中是由編譯器處理的符號(hào),它的功能是取得標(biāo)號(hào)的偏移地址。

            段內(nèi)短轉(zhuǎn)移
            jmp short 標(biāo)號(hào) 功能:IP=IP+8位位移
            1、8位位移=標(biāo)號(hào)處的地址-jmp指令后的第一個(gè)字節(jié)的地址;
            2、short指明此處的位移為8位位移;
            3、8位位移的范圍為-128~127,用補(bǔ)碼表示;
            4、8位位移由編譯程序在編譯時(shí)算出。
            段內(nèi)近轉(zhuǎn)移
            jmp near ptr 標(biāo)號(hào) 功能:IP=IP+16位位移
            1、16位位移=標(biāo)號(hào)處的地址-jmp指令后的第一個(gè)字節(jié)的地址;
            2、near ptr指明此處的位移為16位位移,進(jìn)行的是段內(nèi)近轉(zhuǎn)移;
            3、16位位移的范圍為-32768~32767,用補(bǔ)碼表示;
            4、16位位移由編譯程序在編譯時(shí)算出。
            段間轉(zhuǎn)移
            jmp far ptr 標(biāo)號(hào) 實(shí)現(xiàn)的是段間轉(zhuǎn)移,又稱為遠(yuǎn)轉(zhuǎn)移。功能:
            cs=標(biāo)號(hào)所在段的段地址;ip=標(biāo)號(hào)在段中的偏移地址。
            far ptr指明了指令用標(biāo)號(hào)的段地址和偏移地址修改CS和IP。

            所有的有條件轉(zhuǎn)移指令都是短轉(zhuǎn)移,在對(duì)應(yīng)的機(jī)器碼中包含轉(zhuǎn)移的位移,而不是目的地址。對(duì)IP的修改范圍都為-128~127.
            jcxz 標(biāo)號(hào) == if((cx)==0) jmp short 標(biāo)號(hào)

            所有的循環(huán)指令都是短轉(zhuǎn)移,在對(duì)應(yīng)的機(jī)器碼中包含轉(zhuǎn)移的位移,而不是目的地址。對(duì)IP的修改范圍都為-128~127.
            loop 標(biāo)號(hào) == (cx)--;if((cx)!=0) jmp short 標(biāo)號(hào)

            段內(nèi)轉(zhuǎn)移對(duì)IP的修改時(shí)根據(jù)轉(zhuǎn)移目的地址和轉(zhuǎn)移起始地址之間的位移來進(jìn)行的。在它們對(duì)應(yīng)的機(jī)器碼中不包含轉(zhuǎn)移的目的地址,而包含的是到目的地址的位移。這種設(shè)計(jì),方便了程序段在內(nèi)存中的浮動(dòng)裝配。
            注意,根據(jù)位移進(jìn)行轉(zhuǎn)移的指令,它們的轉(zhuǎn)移范圍受到轉(zhuǎn)移位移的限制,如果在源程序中出現(xiàn)了轉(zhuǎn)移范圍超界的問題,在編譯的時(shí)候,編譯器將報(bào)錯(cuò)。---看到這個(gè)結(jié)論,我心里高興放心多了,不然我還擔(dān)心要我自己去算轉(zhuǎn)移位移呢!

               
            第10章 call和ret指令
            call和ret指令都是轉(zhuǎn)移指令,他們都修改ip,或同時(shí)修改cs和ip。他們經(jīng)常被共同用來實(shí)現(xiàn)子程序的設(shè)計(jì)。
            ret指令用棧中的數(shù)據(jù),修改ip的內(nèi)容,從而實(shí)現(xiàn)近轉(zhuǎn)移。
            retf指令用棧中的數(shù)據(jù),修改cs和ip的內(nèi)容,從而實(shí)現(xiàn)遠(yuǎn)轉(zhuǎn)移。
            ret == "pop IP"
            retf == "pop IP ; pop CS"

            CPU執(zhí)行call指令時(shí),進(jìn)行兩步操作:
            1、將當(dāng)前的IP或CS和IP壓入棧中;
            2、轉(zhuǎn)移。

            call 標(biāo)號(hào) == “push IP ; jmp near ptr 標(biāo)號(hào)”
            call far ptr 標(biāo)號(hào) == “push CS ; push IP ; jmp far ptr 標(biāo)號(hào)”
            call 16位reg == "push IP ; jmp 16位reg"
            call word ptr 內(nèi)存單元地址 == "push IP ; jmp word ptr 內(nèi)存單元地址"
            call dword ptr 內(nèi)存單元地址 == "push CS ; push IP ;jmp dword ptr 內(nèi)存單元地址"

            mul乘法指令:
            1、兩個(gè)相乘的數(shù),要么都是8位,要么都是16位。如果是8位,一個(gè)默認(rèn)在AL中,另一個(gè)放在8位reg或內(nèi)存單元中;如果是16位,一個(gè)默認(rèn)在AX中,另一個(gè)放在16位reg或內(nèi)存字單元中。
            2、結(jié)果:如果是8位乘法,結(jié)果默認(rèn)放在AX中;如果是16位乘法,結(jié)果高位默認(rèn)在DX中,低位在AX中放。

             

            第11章 標(biāo)志寄存器
            標(biāo)志寄存器的3種作用:
            1、用來存儲(chǔ)相關(guān)指令的某些執(zhí)行結(jié)果;
            2、用來為CPU執(zhí)行相關(guān)指令提供行為依據(jù);
            3、用來控制CPU的相關(guān)工作方式。
            flag和其他寄存器不一樣,其他寄存器是用來存放數(shù)據(jù)的,都是整個(gè)寄存器具有一個(gè)含義。而flag寄存器是按位起作用的,也就是說,它的每一位都有專門的含義,記錄特定的信息。
            flag寄存器各位示意圖:

            flag的1、3、4、12、13、14、15位在8086CPU中沒有使用,不具有任何含義。

            CF:進(jìn)位標(biāo)志位。一般情況下,在進(jìn)行無符號(hào)數(shù)運(yùn)算的時(shí)候,它記錄了運(yùn)算結(jié)果的最高有效位向更高位的進(jìn)位值,或從更高位的借位值。
            PF:奇偶標(biāo)志位
            AF:
            ZF:零標(biāo)志位
            SF:符號(hào)標(biāo)志位
            DF:方向標(biāo)志位
            OF:溢出標(biāo)志位。一般情況下,OF記錄了有符號(hào)數(shù)運(yùn)算的結(jié)果是否發(fā)生了溢出。如果發(fā)生溢出,OF=1;如果沒有,OF=0.
            一定要注意CF和OF的區(qū)別:CF是對(duì)無符號(hào)數(shù)運(yùn)算有意義的標(biāo)志位,而OF是對(duì)有符號(hào)運(yùn)算有意義的標(biāo)志位。

            adc帶進(jìn)位加法指令,它利用了CF位上記錄的進(jìn)位值。
            格式:adc op1,op2
            功能: op1=op1+op2+CF
            注意:如果用到這個(gè)指令,一定要密切注意所有可能影響CF標(biāo)志的指令?。?!

            sbb帶借位減法指令,它利用了CF位上記錄的借位值。
            格式:sbb op1,op2
            功能:op1=op1-op2-CF
            注意:如果用到這個(gè)指令,一定要密切注意所有可能影響CF標(biāo)志的指令?。?!

            CPU提供了cmp指令,也提供了je等條件轉(zhuǎn)移指令,如果將它們配合使用,可以實(shí)現(xiàn)根據(jù)比較結(jié)果進(jìn)行轉(zhuǎn)移的功能。但這只是“如果”,只是一種合理的建議,和事實(shí)上常用的方法。但究竟是否配合使用它們,完全是你自己的事情。這就好像call和ret指令的關(guān)系一樣。

            DF標(biāo)志和串傳送指令
            DF:方向標(biāo)志位。在串處理指令中,控制每次操作后si、di的增減。
            df=0 每次操作后si、di遞增;
            df=1 每次操作后si、di遞減。
            cld指令:將標(biāo)識(shí)寄存器的df位置0
            std指令:將標(biāo)識(shí)寄存器的df位置1

            串傳送指令:
            movsb:將ds:di指向的內(nèi)存單元中的字節(jié)送入es:di中,然后根據(jù)標(biāo)志寄存器df位的值,將si和di遞增或遞減。
            功能相當(dāng)于如下幾步:
            1、((es)*16+(di))=((ds)*16+(si))
            2、如果df=0,則:(si)=(si)+1 , (di)=(di)+1
               如果df=1,則:(si)=(si)-1 , (di)=(di)-1
              
            movsw:將ds:di指向的內(nèi)存單元中的字送入es:di中,然后根據(jù)標(biāo)志寄存器df位的值,將si和di遞增2或遞減2。
            功能相當(dāng)于如下幾步:
            1、((es)*16+(di))=((ds)*16+(si))
            2、如果df=0,則:(si)=(si)+2 , (di)=(di)+2
               如果df=1,則:(si)=(si)-2 , (di)=(di)-2
             
            movsb和movsw進(jìn)行的是串傳送操作中的一個(gè)步驟,一般來說,movsb和movsw都和rep配合使用,格式如下:
            rep movsb.用匯編語法來描述rep movsb的功能就是:
            s:movsb
            loop s

            pushf的功能是將標(biāo)志寄存器的值壓棧,而popf是從棧中彈出數(shù)據(jù),送入標(biāo)志寄存器中。
            pushf和popf,為直接訪問標(biāo)志寄存器提供了一種方法。

             

            第12章 內(nèi)中斷
            中斷向量表:對(duì)于8086PC機(jī),中斷向量表指定放在內(nèi)存地址0處。從內(nèi)存0000:0000到0000:03FF的1024個(gè)單元中存放。
            中斷向量表的一個(gè)表項(xiàng)占兩個(gè)字,高地址字存放段地址,低地址字存放偏移地址。

            8086CPU在收到中斷信息后,引發(fā)中斷過程:
            1、從中斷信息中取得中斷類型碼;
            2、標(biāo)志寄存器的值入棧;
            3、設(shè)置標(biāo)志寄存器的第8位TF和第9位IF的值為0;
            4、CS的內(nèi)容入棧;
            5、IP的內(nèi)容入棧;
            6、從內(nèi)存地址為中斷類型碼*4 和 中斷類型碼*4+2 的兩個(gè)字單元中讀取中斷處理程序的入口地址設(shè)置IP和CS。
            更簡(jiǎn)潔的描述:
            1、取得中斷類型碼N;
            2、pushf
            3、TF=0,IF=0
            4、push CS
            5、push IP
            6、(IP)=(N*4),(CS)=(N*4+2)
            TF和IF設(shè)為0,是為了避免在中斷程序處理過程中還是單步調(diào)試狀態(tài)。

            中斷處理程序的編寫方法和子程序的比較相似,下面是常規(guī)步驟:
            1、保存用到的寄存器;
            2、處理中斷;
            3、恢復(fù)用到的寄存器;
            4、用iret指令返回。
            iret指令的功能用匯編語法描述為:
            pop IP
            pop CS
            popf

            定制中斷處理程序,就是將中斷處理程序代碼寫到固定的內(nèi)存地址,然后修改中斷向量表中該中斷類型對(duì)應(yīng)的處理程序的偏移地址。

             

            第13章 int指令
            int指令和iret指令的配合使用與call指令和ret指令的配合使用具有相似的思路。
            編寫中斷例程,就類似于編寫子程序,我們希望中斷處理完成后能繼續(xù)回到原程序繼續(xù)運(yùn)行,所以應(yīng)該使得中斷例程返回。像上一章中中斷程序用int 21h終止進(jìn)程的情況是很特殊的。不過要注意的是,中斷例程的返回需要用iret!

            BIOS和DOS所提供的中斷例程
            在系統(tǒng)板的ROM中存放著一套程序,稱為BIOS(基本輸入輸出系統(tǒng)),BIOS中主要包含以下幾部分內(nèi)容。
            1、硬件系統(tǒng)的檢測(cè)和初始化程序;
            2、外部中斷和內(nèi)部中斷的中斷例程;
            3、用于對(duì)硬件設(shè)備進(jìn)行I/O操作的中斷例程;
            4、其他和硬件系統(tǒng)相關(guān)的中斷例程。
            操作系統(tǒng)DOS也提供了中斷例程,從操作系統(tǒng)的角度來看,DOS的中斷例程就是操作系統(tǒng)向程序員提供的編程資源。
            BIOS和DOS在所提供的中斷例程中包含了許多子程序,這些子程序?qū)崿F(xiàn)了程序員在編程的時(shí)候經(jīng)常需要用到的功能。程序員在編程的時(shí)候,可以用int指令直接調(diào)用BIOS和DOS提供的中斷例程,來完成某些工作。
            和硬件設(shè)備相關(guān)的DOS中斷例程中,一般都調(diào)用了BIOS的中斷例程。

            BIOS和DOS中斷例程安裝過程:
            1、開機(jī)后,CPU一加電,初始化CS=0FFFFH,IP=0,自動(dòng)從FFFF:0單元開始執(zhí)行程序。FFFF:0處有一條跳轉(zhuǎn)指令,CPU執(zhí)行該指令后,轉(zhuǎn)去執(zhí)行BIOS中的硬件系統(tǒng)檢測(cè)和初始化程序。
            跳轉(zhuǎn)指令:jmp F000:998A
            此處的指令不可修改!
            2、初始化程序?qū)⒔IOS所支持的中斷向量,即將BIOS提供的中斷例程的入口地址登記在中斷向量表中。注意,對(duì)于BIOS所提供的中斷例程,只需將入口地址登記在中斷向量表中即可,因?yàn)樗鼈兪枪袒絉OM中的程序,一直在內(nèi)存中存在。
            3、硬件系統(tǒng)檢測(cè)和初始化完成后,調(diào)用int 19h進(jìn)行操作系統(tǒng)的引導(dǎo)。從此將計(jì)算機(jī)交由操作系統(tǒng)控制。
            證明int 19h只是BIOS提供的功能。
            4、DOS啟動(dòng)后,除完成其他工作外,還將它所提供的中斷例程裝入內(nèi)存,并建立相應(yīng)的中斷向量。

            BIOS中斷例程:
            int 10h中斷例程是BIOS提供的中斷例程,其中包含了多個(gè)和屏幕輸出相關(guān)的子程序。
            一般來說,一個(gè)供程序員調(diào)用的中斷例程中往往包括多個(gè)子程序,中斷例程內(nèi)部用傳遞進(jìn)來的參數(shù)來決定執(zhí)行哪一個(gè)子程序。BIOS和DOS提供的中斷例程,都用ah來傳遞內(nèi)部子程序的編號(hào)。

            DOS中斷例程:
            int 21h中斷例程是DOS提供的中斷例程,其中包含了DOS提供給程序員在編程時(shí)調(diào)用的子程序。

             

            第14章 端口
            我們前面講過,各種存儲(chǔ)器都和CPU的地址線、數(shù)據(jù)線、控制線相連。CPU在操控它們的時(shí)候,把它們都當(dāng)做內(nèi)存來對(duì)待,把它們總地看做一個(gè)由若干存儲(chǔ)單元組成的邏輯存儲(chǔ)器,這個(gè)邏輯存儲(chǔ)器我們稱其位內(nèi)存地址空間。
            在PC機(jī)系統(tǒng)中,和CPU通過總線相連的芯片除各種存儲(chǔ)器外,還有以下3中芯片。
            1、各種接口卡(比如,網(wǎng)卡、顯卡)上的接口芯片,他們控制接口卡進(jìn)行工作;
            2、主板上的接口芯片,CPU通過它們對(duì)部分外設(shè)進(jìn)行訪問;
            3、其他芯片,用來存儲(chǔ)相關(guān)的系統(tǒng)信息,或進(jìn)行相關(guān)的輸入輸出處理。
            在這些芯片中,都有一組可以由CPU讀寫的寄存器。這些寄存器,它們?cè)谖锢砩峡赡芴幱诓煌男酒校撬麄冊(cè)谝韵聝牲c(diǎn)上相同。
            1、都和CPU的總線相連,當(dāng)然這種連接是通過它們所在的芯片進(jìn)行的。
            2、CPU對(duì)它們進(jìn)行讀或?qū)懙臅r(shí)候都通過控制線向它們所在的芯片發(fā)出端口讀寫命令。
            可見,從CPU的角度,將這些寄存器都當(dāng)做端口,對(duì)它們進(jìn)行統(tǒng)一編址,從而建立了一個(gè)統(tǒng)一的端口地址空間。每一個(gè)端口在地址空間中都有一個(gè)地址。
            #######問題:
            1、如何將某個(gè)芯片綁定到某個(gè)端口?還是操作系統(tǒng)預(yù)設(shè)的?那要是出現(xiàn)沖突怎么辦?
            2、端口地址空間被內(nèi)存地址空間是同一個(gè)嗎?也就是說:端口地址空間是內(nèi)存地址空間的一個(gè)子集,還是另一個(gè)獨(dú)立的地址空間?
            3、這里講的端口與網(wǎng)絡(luò)程序中說的端口是一個(gè)概念嗎?

            CPU可以直接讀寫以下3個(gè)地方的數(shù)據(jù)。
            1、CPU內(nèi)部的寄存器;
            2、內(nèi)存單元;
            3、端口。

            端口的讀寫
            在訪問端口的時(shí)候,CPU通過端口地址來定位端口,因?yàn)槎丝谒诘男酒虲PU通過總線相連,所以,端口地址和內(nèi)存地址一樣,通過地址總線來傳送。在PC系統(tǒng)中,CPU最多可以定位64KB個(gè)不同的端口。則端口地址的范圍為0~65535.
            對(duì)端口的讀寫不能用mov、push、pop等內(nèi)存讀寫指令。端口的讀寫指令只有兩種:in和out,分別用于從端口讀取數(shù)據(jù)和往端口寫入數(shù)據(jù)。
            注意,在in和out指令中,只能使用ax或al來存放從端口中讀入的數(shù)據(jù)或要發(fā)送到端口中的數(shù)據(jù)。訪問8為端口時(shí)用al,訪問16位端口時(shí)用ax。
            對(duì)0~255以內(nèi)的端口進(jìn)行讀寫時(shí),地址直接寫端口號(hào)。
            in al,20h ;從20h端口讀入一個(gè)字節(jié)
            out 20h,al ;往20h端口寫入一個(gè)字節(jié)
            對(duì)256~65535的端口讀寫時(shí),端口號(hào)放在dx中。
            mov dx,3f8h   ;將端口號(hào)3f8h送入dx
            in al,dx   ;從3f8h端口讀入一個(gè)字節(jié)
            out dx,al   ;想3f8h端口寫入一個(gè)字節(jié)

            對(duì)存儲(chǔ)芯片的操作需要兩個(gè)端口:地址端口和數(shù)據(jù)端口,讀寫分兩步進(jìn)行,先將單元號(hào)送地址端口,然后再利用數(shù)據(jù)渡口進(jìn)行讀或者寫。
            但對(duì)一些別的外設(shè),比如鍵盤輸入,就只有一個(gè)端口。
            但是如何知道一個(gè)芯片到底有多少個(gè)有效單元呢?有指令能查詢嗎?

            shl和shr邏輯移位指令:
            shl是邏輯左移指令,功能為:
            1、將一個(gè)寄存器或內(nèi)存單元中的數(shù)據(jù)向左移位;
            2、將最后移出的一位寫入CF中;
            3、最低位用0補(bǔ)充。
            如果移動(dòng)位數(shù)大于1時(shí),必須將移動(dòng)位數(shù)放在cl中。

            shr是邏輯右移指令,功能為:
            1、將一個(gè)寄存器或內(nèi)存單元中的數(shù)據(jù)向右移位;
            2、將最后移出的一位寫入CF中;
            3、最高位用0補(bǔ)充。
            如果移動(dòng)位數(shù)大于1時(shí),必須將移動(dòng)位數(shù)放在cl中。

             

            第15章 外中斷
            在PC系統(tǒng)中,外中斷源一共有以下兩類:
            1、可屏蔽中斷
            可屏蔽中斷是CPU可以不響應(yīng)的外中斷。CPU是否相應(yīng)可屏蔽中斷,要看標(biāo)志寄存器的IF位的設(shè)置。當(dāng)CPU檢測(cè)到可屏蔽中斷信息時(shí),如果IF=1,則CPU在執(zhí)行完當(dāng)前指令后相應(yīng)中斷,引發(fā)中斷過程;如果IF=0,則不響應(yīng)可屏蔽中斷。
            2、不可屏蔽中斷
            不可屏蔽中斷是CPU必須響應(yīng)的外中斷。當(dāng)CPU檢測(cè)到不可屏蔽中斷信息時(shí),則在執(zhí)行完當(dāng)前指令后,立即響應(yīng),引發(fā)中斷過程。
            對(duì)于8086CPU,不可屏蔽中斷的中斷類型碼固定為2,所以中斷過程中,不需要取中斷類型碼。
            幾乎所有由外設(shè)引發(fā)的外中斷,都是可屏蔽中斷。

            CPU對(duì)外設(shè)輸入的通常處理方法:
            1、外設(shè)的輸入送入端口;
            2、向CPU發(fā)出外中斷(可屏蔽中斷)信息;
            3、CPU檢測(cè)到可屏蔽中斷信息,如果IF=1,CPU在執(zhí)行完當(dāng)前指令后響應(yīng)中斷,執(zhí)行響應(yīng)的中斷例程;
            4、可在中斷例程中實(shí)現(xiàn)對(duì)外設(shè)輸入的處理。
            端口和中斷機(jī)制,是CPU進(jìn)行I/O的基礎(chǔ)。

             

            第16章 直接定址表
            注意:標(biāo)號(hào)定位的是絕對(duì)地址,如果需要將程序安裝到別的地址,類似于中斷程序,由標(biāo)號(hào)定位的地址可能產(chǎn)生錯(cuò)誤。

             

            《80x86匯編語言程序設(shè)計(jì)教程》學(xué)習(xí)筆記
            8086指令系統(tǒng)
            8086指令系統(tǒng)可分為如下六個(gè)功能組:
            1、數(shù)據(jù)傳送
            2、算術(shù)運(yùn)算
            3、邏輯運(yùn)算
            4、串操作
            5、程序控制
            6、處理器控制
            對(duì)于每一條指令,程序員要注意:
            1、指令的功能;
            2、適用于指令的操作數(shù)的尋址方式;
            3、指令對(duì)標(biāo)志的影響;
            4、指令的長(zhǎng)度和執(zhí)行時(shí)間。

            數(shù)據(jù)傳送指令組又可分為:傳送指令,交換指令,地址傳送指令,堆棧操作指令,標(biāo)志傳送指令,查表指令,輸入輸出指令。
            除了SAHF和POPF指令外,這組指令對(duì)各標(biāo)志沒有影響。
            傳送指令mov;變換指令xchg;
            地址傳送指令LEA:lea reg,oprd 該指令把操作數(shù)oprd的有效地址傳送到操作數(shù)reg。
            LDS:lds reg,oprd 該指令把操作數(shù)oprd中所含的一個(gè)32位地址指針的段值部分送到數(shù)據(jù)段寄存器DS,把偏移部分送到指令給出的通用寄存器REG。
            LES:les reg,oprd 該指令把操作數(shù)oprd中所含的32位地址指針的段值部分送到附加段寄存器ES,把偏移部分送到指令給出的通用寄存器reg。
            入棧push;出棧pop。
            標(biāo)志傳送指令:
            LAHF:該指令把標(biāo)志寄存器的低8位(包括SF、ZF、AF、PF、CF)傳送到AH的指定位。
            SAHF:與LAHF相反,把AH的指定位送到標(biāo)志寄存器的低8位。
            PUSHF/POPF.
            標(biāo)志位操作指令,屬于處理器控制指令組:
            CLC:使進(jìn)位標(biāo)志為0
            STC:使進(jìn)位標(biāo)志為1
            CMC:使進(jìn)位標(biāo)志取反。
            CLD:使方向標(biāo)志DF=0.
            STD:使DF=1
            CLI:IF=0
            STI:IF=1

             

            posted on 2012-06-13 16:51 Tim 閱讀(1757) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 匯編語言

            <2012年6月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            1234567

            導(dǎo)航

            統(tǒng)計(jì)

            公告

            本博客原創(chuàng)文章,歡迎轉(zhuǎn)載和交流。不過請(qǐng)注明以下信息:
            作者:TimWu
            郵箱:timfly@yeah.net
            來源:m.shnenglu.com/Tim
            感謝您對(duì)我的支持!

            留言簿(9)

            隨筆分類(173)

            IT

            Life

            搜索

            積分與排名

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            欧美激情精品久久久久| 久久国产乱子精品免费女| 亚洲а∨天堂久久精品9966| 激情久久久久久久久久| 日本国产精品久久| 无码国内精品久久人妻蜜桃| 国产91色综合久久免费分享| 久久精品国产精品亚洲人人| 久久精品人妻中文系列| 久久精品视频网| 亚洲国产日韩综合久久精品| 99久久免费国产精品热| 久久久久久一区国产精品| 国产精品一区二区久久不卡| 久久人人爽人人爽人人片AV东京热| 狠狠色婷婷久久综合频道日韩| 99久久国产热无码精品免费久久久久| 久久亚洲国产精品123区| 久久精品国产亚洲AV高清热| 久久青青草原亚洲av无码| 97久久超碰国产精品2021| 亚洲国产日韩综合久久精品| 99久久人人爽亚洲精品美女| 亚洲国产美女精品久久久久∴| 久久av免费天堂小草播放| 国产成人久久AV免费| 久久久精品人妻一区二区三区蜜桃 | 一级做a爰片久久毛片人呢| 波多野结衣久久精品| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 久久免费线看线看| 久久天天躁夜夜躁狠狠| 一本一道久久a久久精品综合| 久久成人精品| 国产精品亚洲美女久久久| 2021国产成人精品久久| 99久久精品免费国产大片| 九九久久99综合一区二区| 9久久9久久精品| 国产免费久久精品丫丫|