紀念第一次發技術鐵 拉回來瞧瞧 關於int 9

2021-05-17 14:21:00 字數 2901 閱讀 8063

初學彙編時在王爽彙編論壇扔的帖子 第一次發技術鐵 紀念紀念  寫完後一直沒人鳥

遇到的問題:

1.   能否不呼叫原int 9例程

2.   **中沒有int的顯式呼叫,之前的程式為何有

3.   檢測點15.1

4.   多了個pushf,之前的程式為何沒加

對於原因我們分析有2:

1.  從12章開始自己修改中斷例程而慢慢形成的慣性思維

2.  15.4和15.5的標題以及內容對我們誤導

請記住,15章前我們確實在修改或編寫中斷例程,但對於int 9,至少《組合語言》讓我們無能為力,我們在15章做的,嚴格的講連對於這個中斷例程作用的擴充都不算。

子程式和中斷例程都分2塊--呼叫+實現:

call 標號,        程式體(從標號到ret)

int n,                n號中斷的程式體(到iret結束)

對於int 9的這2部分,我們什麼都沒做,除了把進入其實現的入口轉移了地方。。。

為方便理解,我們姑且先把它叫作「鍵盤驅動例程」,並以15.4的程式為例

作者寫的很清楚,我們不能像之前那樣直接扔掉中斷例程,因為它處理了按鍵輸入的很多細節,否則cpu怎麼知道你的指頭在鍵盤上幹了什麼。如果扔掉,那我們自己寫的**只能讓系統識別esc這1個鍵(變色)。我們確實也只做了這件事。

我們知道,

call做了-- (push cs) push ip

ret做了        -- pop ip

int做了:

1. pushf

2. if/tf = 0

3. push cs

4. push ip

5. 讓cpu到新的cs:ip處 (請一定記好這幾步!!並與iret對比)

iret做了:

。。。                        (特定功能實現**)

pop ip

pop cs

popf                        (也請一定記好)

在15章前,(除了int 21h)我們的程式裡有類似int 7ch這樣的int顯式呼叫,完成了上述5步。而15.4和15.5的程式中卻沒有!!

因為「鍵盤輸入到達60h埠後,就會引發9號中斷,cpu則轉去執行int 9中斷例程」,所以當執行程式時只要有鍵盤輸入,就會隱式呼叫int 9,遂我們寫的**中不需要顯式宣告!

那麼此時,

1. pushf

2. if/tf = 0

3. push cs

4. push ip

5. 讓cpu到新的cs:ip處

均已執行!!

接著根據新cs:ip的引導,我們來到了自己寫的**段,繼續執行:

push ax

push bx

push es

。。。        (只分析棧)

pushf        (有網友說flags已經在之前的int呼叫下入棧了,這句貌似多餘。下面分析)

監測點15.1省略的**段(隱式呼叫的int已置if/tf為0,所以才能省略)

call 「鍵盤驅動例程」,=

「鍵盤驅動例程」 =

...

pop es

pop bx

pop ax

iret =

您看出什麼了?

曾經,我們--

鍵盤輸入->

int 9中斷 =

->

「鍵盤驅動程式」 =

如此和諧!!

但因為在2者間插入諸如push ax, push bx,call(特別是call。。)這樣影響int 9幸福生活的不和諧因素,導致flags/cs/ip進出棧順序混亂。。

所以,我們只能配合call而加入pushf,2者一同去「中和」「抵消」下面的「鍵盤驅動例程」返回時的iret(它本就是身份高貴的中斷例程,所以是iret而不是ret)

而最初的int呼叫產生的

pushf, push cs, push ip

由我們自己編寫的**,在最後由iret中和

pop ip, pop cs, popf

綜上,棧的發展:

pushf                (int)

push cs                (int)

push ip                (int)

push ax        

push bx

push es

pushf

push cs                (call)

push ip                (call)

pop ip                (iret 例程的)

pop cs                (iret 例程的)

popf                (iret 例程的)

pop es

pop bx

pop ax

pop ip                (iret 我們寫的)

pop cs                (iret 我們寫的)

popf                (iret 我們寫的)

總結:

1.   15.4.2中的誤導--「int過程的模擬」「標誌暫存器入棧,可用pushf實現」。

int已經隱式完成,標誌暫存器已經入棧,pushf在實現「中和」「抵消」。這也是15章前我們寫的程式中沒有多加「pushf」的原因。

2.   中斷例程的2部分--呼叫+實現,我們都沒有改動,準確的說是沒能力。

我們做的只是改變實現部分呼叫的入口(呼叫時機),也就是在該「鍵盤驅動例程」的前後加了幾行**,僅此而已。

紀念第一次寫部落格

這是我本人第一次在csdn上寫部落格,謹以此來紀念一下這一偉大的時刻 我希望我能堅持將部落格寫下去,記錄下自己的學習成長的過程。看看自己做到了什麼,給自己乙個激勵,然後繼續向著自己的理想前進。馬上就要保研了 也有可能出國 希望能進入自己的想去的學校,學自己感興趣的東西,將來能有一番作為。這個作為,我...

紀念第一次線上筆試

第一次線上筆試 第一次線上筆試,因為自學且c 年代久遠,所以考試的時候第一沒時間了,第二什麼都忘記了,浪費了不少時間,最只做出一道題,雖然非常丟人被朋友笑菜,但畢竟是值得紀念的一次,就將還記得的三道題寫在部落格上 可能我現在寫的 還是錯的,歡迎指正吶,比心 在一串字串中尋找sangfor的個數 如s...

紀念第一次安裝ubuntu

紀念第一次安裝ubuntu 這裡寫自定義目錄標題 通過介紹進入了一家路由器和網路模組研發公司的研發實驗室做fae,由於以前未接觸過硬體開發,而且嵌入式和c用的也是少之又少,導致進公司第一天就壓力滿滿,領導給的任務是安裝虛擬機器,然後安裝ubuntu,然後在ubuntu中使用無線網絡卡鏈結手機的熱點或...