天天看點

拓展:彙編語言的子程式

  一個簡單的包含子程式的彙程式設計式是:

  編譯、連接配接後,用debug觀察到:

拓展:彙編語言的子程式

  從<code>call</code>對應的機器指令中,可以看到這是一種近(near)調用,機器指令<code>eb0500</code>中可以取出要調用的子程式,其偏移位址的位移是<code>0005</code>。

  進一步,用t指令,可以觀察在調用子程式時,棧的變化過程,進而深刻了解子程式的機理。

  編譯、連接配接,用debug載入後,我們觀察:

拓展:彙編語言的子程式

  這就是遠調用!在機器指令中,直接指定了子程式的cs和ip。

  繼續單步執行,觀察在調用過程中棧的變化。這個觀察,對我們了解程式設計中的子程式機制非常重要。

  下面,要将程式變個樣。話從何說起呢?我懷念c語言中的<code>{}</code>了。将一段邏輯上相關的代碼,放在<code>{}</code>中,看起來就有邊有沿的,整齊,帶來的好處,可讀性提高,更關鍵的好處,程式的可讀性提高。

  于是有了下面的寫法。

  從中看到,一個程式,分為若幹個子程式,每個子程式長下面的樣子:

  最為關鍵的就是,将一段程式,我們認為是邏輯功能獨立的子程式,用兩個關鍵字,<code>proc</code>和<code>endp</code>,包圍成了一個整體。

  子程式的名稱,其實質也是代碼的位址。如果子程式就是從第一條指令開始,按下面的寫法也行:

冥冥中,我看到我c中的:

  子產品化的味道出來了吧?

  我們更進一步!

  有人說,彙編隻能編小程式。

  我替我彙說:不服!

  當編大程式時,分子產品做就行了。更關鍵的,從工程組織的角度,進階語言能夠将代碼分别寫在多個檔案中,彙編語言照樣能這麼幹!

  怕有人郁悶,我悄悄地告訴大家,這一招,進階語言是從彙編語言處學的。其實,程式設計技術都是相通的,大家不要搞得不像一家人。

  把上面的程式,分在兩個檔案中,一個檔案中一個子程式:

  step 1:建立“主程式”檔案

  将p1.asm單獨編譯:

拓展:彙編語言的子程式

  強烈建議:将<code>extrn subp:far</code>省略掉,看看會出現什麼?

  step 2:建立“子程式”檔案

   編譯p2.asm:

拓展:彙編語言的子程式

  step 3:連接配接

  上述的兩個.asm經過編譯後,産生了兩個.obj檔案,分别是p1.obj和p2.obj。現在要做的工作,就是把這兩個目标檔案連接配接成一個可執行檔案。

  用的指令是:

拓展:彙編語言的子程式

  連接配接的結果,産生了可執行檔案p1.exe。

  同學們,知道“連接配接”是什麼意思了吧?再來多個檔案,繼續”+”好了。大工程,真的不懼。

  提示:将step 2中的<code>public subp</code>去掉,看看連接配接中會出現什麼問題。進一步思考,在連接配接中有什麼要求

  step 4:運作程式

  駕輕就熟的事情,debug就行。

拓展:彙編語言的子程式

  

  “子程式”的代碼哪去了?

  可以發現,現在隻是“主程式”的代碼,主程式在076b段,而子程式,從子程式調用的指令看,在076d段。

  繼續看:

拓展:彙編語言的子程式

  呵呵,這就找到了。

  本文用一個很簡單的例子,介紹了彙編語言引入子程式後,程式的結構,以及多檔案組織的形式。程式簡單了些,但道理都在裡面呢。

  可以做一個練習,主程式調用子程式玩一玩。

【練習】

  (1)版本1:子程式的參數由寄存器dl提供,傳回結果在ax中;

  (2)版本2:子程式不變,主程式中提供如下資料區,在主程式中,循環調用子程式,完成y=x4的求解,并将結果存入在相應的資料區:

  (3)版本3:資料區不變,子程式完成全部8個資料的求解任務,主程式隻調用一次子程式即可。資料x的起始偏移位址由si提供,存放結果的y的偏移位址,由di提供,在調用前,由主程式為子程式提供si、di值。

  (4)版本4:将上面的程式按多檔案的方式存放。

繼續閱讀