[匯編]《匯編語言》第4章 第一個程序


王爽《匯編語言》第四版 超級筆記

第4章 第一個程序

4.1 一個源程序從寫出到執行的過程

圖4.1描述了一個匯編語言程序從寫出到最終執行的簡要過程。具體說明如下。

image

第一步:編寫匯編源程序。

使用文本編輯器(如Edit、記事本等),用匯編語言編寫匯編源程序。

這一步工作的結果是產生了一個存儲源程序的文本文件。

第二步:對源程序進行編譯連接。

使用匯編語言編譯程序對源程序文件中的源程序進行編譯,產生目標文件;

再用連接程序對目標文件進行連接,生成可在操作系統中直接運行的可執行文件。

可執行文件包含兩部分內容。

  • 程序(從源程序中的匯編指令翻譯過來的機器碼)和數據(源程序中定義的數據)

  • 相關的描述信息(比如,程序有多大、要占用多少內存空間等)

這一步工作的結果:產生了一個可在操作系統中運行的可執行文件。

第三步:執行可執行文件中的程序。

在操作系統中,執行可執行文件中的程序。

操作系統依照可執行文件中的描述信息,將可執行文件中的機器碼和數據加載入內存,並進行相關的初始化(比如設置CS:IP指向第一條耍執行的指令),然后由CPU執行程序。

4.2 源程序、源程序編輯

下面就是一段簡單的匯編語言源程序。

程序4.1

assume cs:codesg

codesg segment

                mov ax,0123H
                mov bx,0456H
                add ax,bx
                add ax,ax

                mov ax,4c00H 
                int 21H

codesg ends

end

下面對程序進行說明。

1、偽指令

在匯編語言源程序中,包含兩種指令,一種是匯編指令,一種是偽指令。

匯編指令是有對應的機器碼的指令,可以被編譯為機器指令,最終為CPU所執行。

而偽指令沒有對應的機器指令,最終不被CPU所執行。

那么誰來執行偽指令呢?

偽指令是由編譯器來執行的指令,編譯器根據偽指令來進行相關的編譯工作。

你現在能看出來程序4.1中哪些指令是偽指令嗎?

程序4.1中出現了3種偽指令。

(1)XXX segment······XXX ends

segment和ends是一對成對使用的偽指令,這是在寫可被編譯器編譯的匯編程序時, 必須耍用到的一對偽指令。

segment和ends的功能是定義一個段,segment說明一個段開始,ends說明一個段結束。

一個段必須有一個名稱來標識,使用格式為:

段名 segment
段名 ends

比如,程序4.1中的:

codesg segment          ;定義一個段,段的名稱為“codesg”,這個段從此開始

codesg ends          ;名稱為“codesg”的段到此結束

一個匯編程序是由多個段組成的,這些段被用來存放代碼、數據或當作棧空間來使用。

我們在前面的課程中所講解的段的概念,在匯編源程序中得到了應用與體現,一個源程序中所有將被計算機所處理的信息:指令、數據、棧,被划分到了不同的段中。

一個有意義的匯編程序中至少要有一個段,這個段用來存放代碼。

我們可以看到,程序4.1中,在codesg segment和codesg ends之間寫的匯編指令是這個段中存放的內容,這是一個代碼段(其中還有我們不認識的指令,后面會進行講解)。

(2)end

end是一個匯編程序的結束標記,編譯器在編譯匯編程序的過程中,如果碰到了偽指令end,就結束對源程序的編譯。

所以,在我們寫程序的時候,如果程序寫完了,要在結尾處加上偽指令end。

否則,編譯器在編譯程序時,無法知道程序在何處結束。

注意,不要搞混了end和ends,ends是和segment成對使用的,標記一個段的結束,ends的含義可理解為“end segment”。

我們這里講的end的作用是標記整個程序的結束。

(3)assume

這條偽指令的含義為“假設”。

它假設某一段寄存器和程序中的某一個用segment...ends定義的段相關聯。

通過assume說明這種關聯,在需要的情況下,編譯程序可以將段寄存器和某一個具體的段相聯系。

assume並不是一條非要深入理解不可的偽指令,以后我們編程時,記着用assume將有特定用途的段和相關的段寄存器關聯起來即可。

比如,在程序4.1中,我們用codesg segment ... codesg ends定義了一個名為codseg的段,在這個段中存放代碼,所以這個段是一個代碼段。

在程序的開頭,用assume cs:codesg 將用作代碼段的段codesg和CPU中的段寄存器cs聯系起來。

2、源程序中的“程序”

用匯編語言寫的源程序,包括偽指令和匯編指令,我們編程的最終目的是讓計算機完成一定的任務。

源程序中的匯編指令組成了最終由計算機執行的程序,而源程序中的偽指令是由編譯器來處理的,它們並不實現我們編程的最終目的。

這里所說的程序就是指源程序中最終由計算機執行、處理的指令或數據。

注意,以后可以將源程序文件中的所有內容稱為源程序,將源程序中最終由計算機執行、處理的指令或數據,稱為程序。

程序最先以匯編指令的形式存在源程序中,經編譯、連接后轉變為機器碼,存儲在可執行文件中。這個過程如圖4.2所示。

image

3、標號

匯編源程序中,除了匯編指令和偽指令外,還有一些標號,比如“codesg”。

一個標號指代了一個地址。比如codesg在segment的前面,作為一個段的名稱,這個段的名稱最終將被編譯、連接程序處理為一個段的段地址。

4、程序的結構

我們現在討論一下匯編程序的結構。

在前3章中,我們都是通過直接在Debug中寫入匯編指令來寫匯編程序,對於十分簡短的程序這樣做的確方便。可對於大一些的程序,就不能如此了。

我們需要寫出能讓編譯器進行編譯的源程序,這樣的源程序應該具備起碼的結構。

源程序是由一些段構成的。我們可以在這些段中存放代碼、數據,或將某個段當作棧空間。

我們現在來一步步地完成一個小程序,從這個過程中體會一下匯編程序中的基本要素和匯編程序的簡單框架。

編程運算2^3,源程序應該怎樣來寫呢?

(1)我們要定義一個段,名稱為abc。

abc segment
        ···
        ···
        ···
abc ends

(2)在這個段中寫入匯編指令,來實現我們的任務。

abc segment

        mov ax,2
        add ax,ax
        add ax,ax

abc ends

(3)然后,要指出程序在何處結束。

abc segment

        mov ax,2
        add ax, ax
        add ax, ax

abc ends

end

(4)abc被當作代碼段來用,所以,應該將abc和cs聯系起來。(當然,對於這個程序,也不是非這樣做不可。)

assume cs:abc

abc segment

        mov ax,2
        add ax, ax
        add ax, ax

abc ends

end

最終寫成的程序如程序4.2所示。

程序4.2

assume cs:abc

abc segment

        mov ax,2
        add ax, ax
        add ax, ax

abc ends

end

5、程序返回

我們的程序最先以匯編指令的形式存在源程序中,經編譯、連接后轉變為機器碼,存儲在可執行文件中,那么它怎樣得到運行呢?

下面,我們在DOS(一個單任務操作系統)的基礎上,簡單地討論一下這個問題。

一個程序P2在可執行文件中,則必須有一個正在運行的程序P1,將P2從可執行文件中加載入內存后,將CPU的控制權交給P2,P2才能得以運行。P2開始運行后,P1暫停運行。

而當P2運行完畢后,應該將CPU的控制權交還給使它得以運行的程序P1,此后P1繼續運行。

我們知道,一個程序結束后,將CPU的控制權交還給使它得以運行的程序,我們稱這個過程為:程序返回

那么,如何返回呢?

應該在程序的末尾添加返回的程序段。

我們回過頭來,看一下程序4.1中的兩條指令:

mov ax,4c00H
int 21H

這兩條指令所實現的功能就是程序返回。

在目前階段,我們不必去理解int21H指令的含義,和為什么要在這條指令的前面加上指令movax,4c00H。

我們只要知道,在程序的末尾使用這兩條指令就可以實現程序返回。

到目前為止,我們好像已經遇到了幾個和結束相關的內容;段結束、程序結束、程序返回。表4.1展示了它們的區別。

image

6、語法錯誤和邏輯錯誤

可見,程序4.2在運行時會引發一些問題,因為程序沒有返回。

當然,這個錯誤在編譯的時候是不能表現出來的,也就是說,程序4.2對於編譯器來說是正確的程序。

一般說來,程序在編譯時被編譯器發現的錯誤是語法錯誤,比如將程序4.2寫成如下這樣就會發生語法錯誤:

aume cs:abc

abc segment

        mov ax,2
        add ax,ax
        add ax, ax

end

顯然,程序中有編譯器不能識別的aume,而且編譯器在編譯的過程中也無法知道abc段到何處結束。

在源程序編譯后,在運行時發生的錯誤是邏輯錯誤。

語法錯誤容易發現,也容易解決。而邏輯錯誤通常不容易被發現。不過,程序4.2中的錯誤卻顯而易見,我們將它改正過來:

assume cs:abc

abc segment

        mov ax,2
        add ax, ax
        add ax, ax

        mov ax,4c00H
        int 21H

abc ends

end

可以用任意的文本編輯器來編輯源程序,只要最終將其存儲為純文本文件即可。

在我們的課程中,使用DOS下的Edit,以程序4.1為例,說明工作過程。

(1)進入DOS方式,運行Edit,如圖4.3所示。

image

(2)在Edit中編輯程序,如圖4.4所示。

image

(3)將程序保存為文件c:\1.asm后,退出Edit,結束對源程序的編輯。

4.3 編譯、連接

完成對源程序的編輯后,得到一個源程序文件c:\1.asm,可以對其進行編譯,生成包含機器代碼的目標文件。

在編譯一個源程序之前首先要找到一個相應的編譯器。

在我們的課程中,采用微軟的masm5.0匯編編譯器,文件名為masm.exe。

假設匯編編譯器在c:\masm目錄下。可以按照下面的過程來進行源程序的編譯,以c:\1.asm為例。

(1)進入DOS方式,進入c:\masm目錄,運行masm.exe,如圖4.5所示。

image

圖4.5中,運行masm后提示輸入將要被編譯的源程序文件的名稱。注意,“[.ASM]”提示我們,默認的文件擴展名是asm。

可如果源程序文件不是以asm為擴展名的話,就要輸入它的全名。

在輸入源程序文件名的時候一定要指明它所在的路徑。如果文件就在當前路徑下,只輸入文件名就可以,可如果文件在其他的目錄中,則要輸入路徑。

比如,要編譯的文件pl.txt在"c:\windows\desktop"下,則要輸入"c:\windows\desktop\pl.txt"。

這里,我們要編譯的文件是C盤根目錄下的1.asm,所以此處輸入“c:\1.asm”。

(2)輸入要編譯的源程序文件名后,按Enter鍵,屏幕顯示如圖4.6所示。

image

圖4.6中,在輸入源程序文件名后,程序繼續提示我們輸入要編譯出的目標文件的名稱,目標文件是我們對一個源程序進行編譯要得到的最終結果。

注意屏幕上的顯示:“[1.OBJ]”,因為我們已經輸入了源程序文件名為1.asm,則編譯程序默認要輸出的目標文件名為1.obj,所以可以不必再另行指定文件名。直接按Enter鍵,編譯程序將在當前的目錄下,生成1.obj文件。

也可以指定生成的目標文件所在的目錄,比如,想讓編譯程序在“c:\windows\desktop”下生成目標文件1.obj,則可輸入“c:\windows\desktop\1”。

我們直接按Enter鍵。

(3)確定了目標文件的名稱后,屏幕顯示如圖4.7所示。

image

圖4.7中,編譯程序提示輸入列表文件的名稱,這個文件是編譯器將源程序編譯為目標文件的過程中產生的中間結果。可以讓編譯器不生成這個文件,直接按Enter鍵即可。

(4)忽略了列表文件的生成后,屏幕顯示如圖4.8所示。

image

圖4.8中,編譯程序提示輸入交叉引用文件的名稱,這個文件同列表文件一樣,是編譯器將源程序編譯為目標文件過程中產生的中間結果。可以讓編譯器不生成這個文件,直接按Enter鍵即可。

(5)忽略了交叉引用文件的生成后,屏幕顯示如圖4.9所示。

image

圖4.9中,對源程序的編譯結束,編譯器輸出的最后兩行告訴我們這個源程序沒有警告錯誤和必須要改正的錯誤。

當然,如果編譯的過程中岀現錯誤,那么將得不到目標文件。

一般來說,有兩類錯誤使我們得不到所期望的目標文件:

1、程序中有“Severe Errors”;
2、找不到所給出的源程序文件。

注意,在編譯的過程中,我們提供了一個輸入,即源程序文件。

最多可以得到3個輸出:目標文件(.obj)、列表文件(.lst)、交叉引用文件(.erf) ,這3個輸出文件中,目標文件是我們最終要得到的結果,而另外兩個只是中間結果,可以讓編譯器忽略對它們的生成。


在對源程序進行編譯得到目標文件后,我們需要對目標文件進行連接,從而得到可執行文件。

我們己經對c:\1.asm進行編譯得到c:\masm\1.obj,現在再將c:\masm\1.obj連接為c:\masm\1.exe。

我們使用微軟的Overlay Linker 3.60連接器,文件名為link.exe,假設連接器在c:\masm目錄下。

可以按照下面的過程來進行程序的連接,以c:\masm\1.obj為例。

(1)進入DOS方式,進入c:\masm目錄,運行link.exe,如圖4.10所示。

image

圖4.10中,運行link后,提示輸入將要被連接的目標文件的名稱。

注意,“[.OBJ]”提示我們,默認的文件擴展名是obj,比如要連接的目標文件名是“pl.obj”,只要在這里輸入“pl”即可。可如果文件不是以obj為擴展名,就要輸入它的全名。

在輸入目標文件名的時候,要注意指明它所在的路徑。這里,要連接的文件是當前目錄下的1.obj,所以此處輸入“1”。

(2)輸入要連接的目標文件名后,按Enter鍵,屏幕顯示如圖4.11所示。

image

圖4.11中,在輸入目標文件名后,程序繼續提示我們輸入要生成的可執行文件的名稱,可執行文件是我們對一個程序進行連接要得到的最終結果。

這里,也可以指定生成的可執行文件所在的目錄,比如,想讓連接程序在"c:\windows\desktop"下生成可執行文件1.EXE,則可輸入“c:\windows\desktop\1"。

我們直接按Enter鍵,使用連接程序設定的可執行文件名。

(3)確定了可執行文件的名稱后,屏幕顯示如圖4.12所示。

image

圖4.12中,連接程序提示輸入映像文件的名稱,這個文件是連接程序將目標文件連接為可執行文件過程中產生的中間結果,可以讓連接程序不生成這個文件,直接按Enter鍵即可。

(4)忽略了映像文件的生成后,屏幕顯示如圖4.13所示。

image

圖4.13中,連接程序提示輸入庫文件的名稱。庫文件里面包含了一些可以調用的子程序,如果程序中調用了某一個庫文件中的子程序,就需要在連接的時候,將這個庫文件和目標文件連接到一起,生成可執行文件。

但是,這個程序中沒有調用任何子程序,這里忽略庫文件名的輸入,直接按Enter鍵即可。

(5)忽略了庫文件的連接后,屏幕顯示如圖4.14所示。

image

圖4.14中,對目標文件的連接結束,連接程序輸出的最后一行告訴我們,這個程序中有一個警告錯誤:“沒有棧段”,這里我們不理會這個錯誤。

當然,如果連接過程中出現錯誤,那么將得不到可執行文件。

這里再次強調一下,我們學習匯編的主要目的,就是通過用匯編語言進行編程而深入地理解計算機底層的基本工作機理,達到可以隨心所欲地控制計算機的目的。

基於這種考慮,我們的編程活動,大都是直接對硬件進行的。我們希望直接對硬件編程,卻並不希望用機器碼編程。

我們用匯編語言編程,就要用到編輯器(Edit)、編譯器(masm)、連接器(link)、調試工具(Debug)等所有工具,而這些工具都是在操作系統之上運行的程序,所以我們的學習過程必須在操作系統的環境中進行。

我們在一個操作系統環境中,使用了許多工具,這勢必要牽扯到操作系統、編譯原理等方面的知識和原理。

我們只是利用這些環境、工具來方便我們的學習,而不希望這些東西分散了我們的注意力。所以,對於涉及而又不在我們學習的主要內容之中的東西,我們只做簡單的解釋。

好了,我們簡單地講連接的作用,連接的作用有以下幾個。

(1)當源程序很大時,可以將它分為多個源程序文件來編譯,每個源程序編譯成為目標文件后,再用連接程序將它們連接到一起,生成一個可執行文件;

(2)程序中調用了某個庫文件中的子程序,需要將這個庫文件和該程序生成的目標文件連接到一起,生成一個可執行文件;

(3)一個源程序編譯后,得到了存有機器碼的目標文件,目標文件中的有些內容還不能直接用來生成可執行文件,連接程序將這些內容處理為最終的可執行信息。所以,在只有一個源程序文件,而又不需要調用某個庫中的子程序的情況下,也必須用連接程序對目標文件進行處理,生成可執行文件。

注意,對於連接的過程,可執行文件是我們要得到的最終結果。

4.4 簡化方式進行編譯和連接

我們編譯、連接的最終目的是用源程序文件生成可執行文件。

在這個過程中所產生的中間文件都可以忽略。我們可以用一種較為簡捷的方式進行編譯、連接。

簡捷的編譯過程如圖4.15 所示。

image

注意圖4.15中的命令行“masm c:\1;”,在masm后面加上被編譯的源程序文件的路徑、文件名,在命令行的結尾再加上分號,按Enter鍵后,編譯器就對c:\1.asm進行編譯,在當前路徑下生成目標文件1.obj,並在編譯的過程中自動忽略中間文件的生成。

圖4.16展示了簡捷的連接過程。

image

注意圖4.16中的命令行“link 1;”,在link后面加上被連接的目標文件的路徑、文件名,在命令行的結尾再加上分號,按Enter鍵后,連接程序就對當前路徑下的1.obj進行處理,在當前路徑下生成可執行文件1.exe,並在過程中自動忽略中間文件的生成。

4.5 匯編程序從寫出到執行的過程

現在,終於將我們的第一個匯編程序加工成了一個可在操作系統下執行的程序文件,我們現在執行一下,圖4.17展示了1.exe的執行情況。

image

奇怪嗎?程序運行后,竟然沒有任何結果,就和沒有運行一樣。

那么,程序到底運行了嗎?

程序當然是運行了,只是從屏幕上不可能看到任何運行結果,因為,我們的程序根本沒有向顯示器輸出任何信息。

程序只是做了一些將數據送入寄存器和加法的操作,而這些事情,我們不可能從顯示屏上看出來。

程序執行完成后,返回,屏幕上再次出現操作系統 的提示符(圖4.17中第2行)。

當然,我們不能總是寫這樣的看不到任何結果的程序,隨着課程的進行,我們將會向顯示器上輸出信息,不過那將是幾章以后的事情了,請耐心等待。


在DOS中,可執行文件中的程序P1若要運行,必須有一個正在運行的程序P2,將P1從可執行文件中加載入內存,將CPU的控制權交給它,P1才能得以運行;

當P1運行完畢后,應該將CPU的控制權交還給使它得以運行的程序P2。

按照上面的原理,再來看一下1.exe的執行過程(思考相關的問題)。

(1)在提示符“c:\masm”后面輸入可執行文件的名字“1”,按Enter鍵。這時,請思考問題4.1。

(2)1.exe中的程序運行。

(3)運行結束,返回,再次顯示提符“c:\masm”。請思考問題4.2。

問題4.1

此時,有一個正在運行的程序將1.exe中的程序加載入內存,這個正在運行的程序是什么?它將程序加載入內存后,如何使程序得以運行?

問題4.2

程序運行結束后,返回到哪里?

如果你對DOS有比較深入的了解,那么,很容易回答問題4.1、問題4.2中所提出的問題。

如果沒有這種了解,可以先閱讀下面的內容。

操作系統的外殼

操作系統是由多個功能模塊組成的龐大、復雜的軟件系統。任何通用的操作系統,都要提供一個稱為shell(外殼)的程序,用戶(操作人員)使用這個程序來操作計算機系統進行工作。

DOS中有一個程序command.com,這個程序在DOS中稱為命令解釋器,也就是DOS系統的shell。

DOS啟動時,先完成其他重要的初始化工作,然后運行command.com,command.com運行后,執行完其他的相關任務后,在屏幕上顯示出由當前盤符和當前路徑組成的提示符,比如:"c:\”或“c:\windows”等,然后等待用戶的輸入。

用戶可以輸入所要執行的命令,比如:cd、dir、type等,這些命令由command執行,command執行完這些命令后,再次顯示由當前盤符和當前路徑組成的提示符,等待用戶的輸入。

如果用戶要執行一個程序,則輸入該程序的可執行文件的名稱,command首先根據文件名找到可執行文件,然后將這個可執行文件中的程序加載入內存,設置CS:IP指向程序的入口。此后,command暫停運行,CPU運行程序。程序運行結束后,返回到command中,command再次顯示由當前盤符和當前路徑組成的提示符,等待用戶的輸入。

在DOS中,command處理各種輸入:命令或要執行的程序的文件名。我們就是通過command來進行工作的。

現在回答問題4.1和4.2。

(1)在DOS中直接執行1.exe時,是正在運行的command,將1.exe中的程序加載入內存;

(2)command設置CPU的CS:IP指向程序的第一條指令(即程序的入口),從而使程序得以運行;

(3)程序運行結束后,返回到command中,CPU繼續運行command。

匯編程序從寫出到執行的過程

到此,完成了一個匯編程序從寫出到執行的全部過程。我們經歷了這樣一個歷程:

編程(Edit)—> 1.asm —> 編譯(masm) —> 1.obj —> 連接(link) —> 1.exe —> 加載(conmiand) —> 內存中的程序 —>運行(CPU)

4.6 程序執行過程的跟蹤

可以用Debug來跟蹤一個程序的運行過程,這通常是必須要做的工作。

下面以在前面的內容中生成的可執行文件1.exe為例,講解如何用Debug對程序的執行過程進行跟蹤。

為了觀察程序的運行過程,可以使用Debug。

Debug可以將程序加載入內存,設置CS:IP指向程序的入口,但Debug並不放棄對CPU的控制,這樣,我們就可以使用Debug的相關命令來單步執行程序,查看每一條指令的執行結果。

具體方法如圖4.18所示。

image

在提示符后輸入"debug 1.exe",按Enter鍵,Debug將程序從1.exe中加載入內存,進行相關的初始化后設置CS:IP指向程序的入口。

接下來可以用R命令看一下各個寄存器的設置情況,如圖4.19所示。

image

可以看到,Debug將程序從可執行文件加載入內存后,cx中存放的是程序的長度。

1.exe中程序的機器碼共有15個字節,則1.exe加載后,cx中的內容為000FH。

現在程序己從1.exe中裝入內存,接下來查看一下它的內容,可是我們查看哪里的內容呢?程序被裝入內存的什么地方?我們如何得知?

這里,需要講解一下在DOS系統中.EXE文件中的程序的加載過程。

圖4.20針對我們的問題,簡要地展示了這個過程。

image

那么,我們的程序被裝入內存的什么地方?我們如何得知?從圖4.20中我們知道以下的信息。

(1)程序加載后,ds中存放着程序所在內存區的段地址,這個內存區的偏移地址為0,則程序所在的內存區的地址為ds:0;

(2)這個內存區的前256個字節中存放的是PSP,DOS用來和程序進行通信。從256字節處向后的空間存放的是程序。

所以,從ds中可以得到PSP的段地址SA,PSP的偏移地址為0,則物理地址為 SAx16+0。

因為PSP占256(100H)字節,所以程序的物理地址是:

SA x 16+0+256 = SA x 16+16x16+0 = (SA+16)x16+0

可用段地址和偏移地址表示為:SA+10H:0。

現在,我們看一下圖4.19中DS的值,DS=129E,則PSP的地址為129E:0,程序的地址為12AE:0(即
129E+10:0)。

圖4.19中,CS=12AE,IP=0000,CS:IP指向程序的第一條指令。

注意,源程序中的指令是mov ax,0123H,在Debug中記為mov ax,0123,這是因為Debug默認所有數據都用十六進制表示。

可以用U命令看一下其他指令,如圖4.21所示。

image

可以看到,從12AE:0000~12AE:000E都是程序的機器碼。

現在,我們可以開始跟蹤了,用T命令單步執行程序中的每一條指令,並觀察每條指令的執行結果,到了int 21,我們要用P命令執行,如圖4.22所示。

image

圖4.22 中,int 21執行后,顯示岀“Program terminated normally”,返回到Debug中。表示程序正常結束。

注意,要使用P命令執行int 21。這里不必考慮是為什么,只要記住這一點就可以了。

需要注意的是,在DOS中運行程序時,是command將程序加載入內存,所以程序運行結束后返回到command中,而在這里是Debug將程序加載入內存,所以程序運行結束后要返回到Debug中。

使用Q命令退出Debug,將返回到command中,因為Debug是由command加載運行的。

在DOS中用"debug 1.exe”運行Debug對1.exe進行跟蹤時。

程序加載的順序是:command加載Debug,Debug加載1.exe。

返回的順序是:從1.exe中的程序返回到Debug,從Debug返回到command。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM