VC++中開發匯編語言(轉)


  1. 匯編程序結構
    1. 一個顯示字符串的匯編程序
    2. 程序格式
      1. 一、模式定義
      2. 二、includelib語句
      3. 三、函數聲明語句
      4. 四、數據和代碼部分
    3. Visual C/C++環境
      1. 建立工程
      2. 匯編程序的調試
        1. 一、設置斷點
        2. 二、內存窗口
        3. 三、寄存器窗口
        4. 四、監視窗口
      3. 常用調試命令
    4. 字符串輸入、輸出
      1. printf
      2. sprintf
      3. scanf
    5. 常用Windows API調用
      1. MessageBox
      2. 確定函數的聲明語句和庫文件
    6. 讀取CPU標識
    7. WinDbg調試工具
    8. 實驗題:用MessageBox函數顯示CPU信息
 源自:http://blog.csdn.net/shijiandehaizi/article/details/8249295

 

Windows、Linux等現代操作系統都運行於CPU的保護模式下。學習保護模式的匯編語言編程,要選用合適的編譯、調試工具,編譯工具決定了匯編程序的語法、結構,而調試工具則能夠幫助我們迅速查找程序中的錯誤,提高調試效率。

本實驗指導書采用Microsoft公司的MASM 6.14作為編譯工具,Microsoft Visual C/C++作為開發調試環境。

1.1 匯編程序結構

和其他語言一樣,匯編語言的源程序也要符合一定的格式,才能被編譯程序所識別和處理。學習和掌握這些格式,是進行匯編編程的第一步。

1.1.1 一個顯示字符串的匯編程序

       下面是一個簡單的匯編程序。

;程序清單:test.asm(在控制台上顯示一個字符串)

.386

.model flat, stdcall

option casemap:none

; 說明程序中用到的庫、函數原型和常量

includelib      msvcrt.lib

printf          PROTO C :ptr sbyte, :vararg

; 數據區

.data

szMsg           byte    “Hello World!”, 0ah, 0

; 代碼區

.code

start:

                mov    eax, OFFSET szMsg

                invoke printf, eax

                ret

end             start

1.1.2 程序格式

在源程序test.asm中,以分號(;)開始的行是注釋行。注釋行對程序的編譯和執行沒有影響。

一、模式定義

程序的第一部分是有關模式定義的3條語句:

.386

.model flat, stdcall

option casemap:none

這些語句定義了程序使用的指令集、工作模式。

(1)指令集

.386語句是匯編語言的偽指令,說明本程序使用的指令集是哪一種CPU的。還可以使用:.8086、.186、.286、.386、.386p、.486、.486p、.586、.586p等。

后面帶p的偽指令則表示程序中可以使用特權指令。

(2)工作模式

.model語句用來定義程序工作的模式,它的格式是:

.model 內存模式[, 調用規則][, 其他模式]

內存模式的定義影響最后生成的可執行文件,可執行文件的規模可以有很多種類型,在Windows環境下,內存模式為flat,可執行文件最大可以用4 GB內存。

在test.asm中,.model語句指明使用stdcall調用規則。調用規則就是子程序的調用方式,即調用子程序時參數傳遞的次序和堆棧平衡的方法。

(3). option語句

option語句有許多選項,這里介紹一種:

option casemap:none

這條語句說明程序中的變量和子程序名是否對大小寫敏感。對大小寫敏感表示區分大寫、小寫形式,例如變量XYZ和xyz是兩個不同的變量。對大小寫不敏感則不區分大寫、小寫形式,變量XYZ和xyz是同一個變量。

由於Windows API函數中的函數名稱是區分大小寫的,所以應該指定這個選項“casemap:none”,否則在調用函數的時候會出現問題。

二、includelib語句

和C程序一樣,在匯編程序中也需要調用一些外部模塊(子程序/函數)來完成部分功能。例如,在hello.asm中,就需要調用printf函數將字符串顯示在屏幕上。

printf函數屬於C語言的庫函數。它的執行代碼放在一個動態鏈接庫DLL(dynamic-load library)中,這個動態庫的名字叫msvcrt.dll。

在匯編源程序中,需要用includelib語句指出庫文件的名稱,鏈接時LINK就從庫文件中找出了函數的位置,避免出現上面的錯誤提示。這種庫文件也叫導入庫(import library)。例如:

includelib      msvcrt.lib

一個DLL文件對應一個導入庫,如msvcrt.dll的導入庫是msvcrt.lib;kernel32.dll的導入庫是kernel32.lib;user32.dll的導入庫是user32.lib等。導入庫文件在Visual C/C++的庫文件目錄中,在鏈接生成可執行文件時使用。

可執行文件執行時,只需要DLL文件,不需要導入庫。

三、函數聲明語句

對於所有要用到的庫函數(或Windows API函數),在程序的開始部分必須預先聲明。包括函數的名稱、參數的類型等,如:

在匯編語言程序中,函數聲明為:

函數名稱            PROTO [調用規則] :[第一個參數類型] [,:后續參數類型]

其中,PROTO后的調用規則是可選項。如果不寫,則使用model語句中指定的調用規則。

如果函數使用C調用規則,則PROTO后跟一個C。接下來是參數的說明。如果參數個數、類型不定,則用VARARG說明(varible argument)。

先看在C語言頭文件stdio.h中printf的函數聲明:

_CRTIMP int __cdecl printf(const char *, ...);

可知printf函數的調用規則為C調用規則(__cdecl, 即c declare),第一個參數是字符串指針,后面的參數數量及類型不定。

這里,用ptr sbyte代表const char *。

printf          PROTO C :ptr sbyte,:vararg

四、數據和代碼部分

程序中的數據部分和代碼部分是分開定義的,數據部分從這一行開始:

.data

代碼部分從這一行開始:

.code

遇到end語句時,代碼部分結束。

end語句一般是整個程序的最后一條語句。end語句后面跟的是起始標號。它指出了程序執行的第一條指令的位置。在例子中,使用start作為起始標號,程序從start處開始執行。注意,程序並不一定要從代碼部分的第一行開始執行。例如,start前面可以寫一些子程序等。

end             起始標號

如果要定義堆棧部分,可以使用堆棧定義語句:

.stack          [堆棧大小]

1.2 Visual C/C++環境

Microsoft Visual C/C++(簡稱VC)是一個典型的集成開發環境(IDE,integrated development environment),在國內外十分流行。集成開發環境大大地提高了程序開發過程的效率,而且它還能夠動態地調試程序。除了可以編寫調試C/C++程序外,VC還可以用來編輯、修改、編譯、調試匯編程序。本書使用的版本是Microsoft Visual C/C++ 6.0。

1.2.1 建立工程

首先,按照以下步驟建立一個能編譯、調試匯編程序的工程:

(1)    啟動VC后,從菜單中選擇“File”→“New”。

(2)    如圖1-1所示,在打開的“New”對話框頂部,單擊“Projects”,再選中“Win32 Console Application”。在Location編輯框中輸入“c:"asm”,再在“Project name”中輸入“test”。輸入“test”時,它自動地添加到Location編輯框中“c:"asm”的后面。

圖1-1 建立匯編程序工程之一

(3)    單擊“OK”鍵后,出現一個新的對話框,單擊“Finish”。

(4)    接下來,VC的窗口的左邊顯示出“test classes”,下面有“ClassView”和“FileView”兩種視圖,如圖1-2所示。

(5)    這時,可將hellow.asm(或其他的一個.asm源程序文件)復制到c:"asm"test中,並改名為test.asm;也可以將其他的匯編程序源文件復制到c:"asm"test"test.asm。

圖1-2 建立匯編程序工程之二

(6)    接下來,再從菜單中選擇“Project”→“Add to Projects”→“Files”,在該對話框中的文件名處輸入“c:"asm"test"test.asm”,如圖1-3所示。

圖1-3 建立匯編程序工程之三

(7)    在VC窗口左邊的視圖中,展開“FileView”中的“Source Files”,顯示出“test.asm”。在“test.asm”上,單擊鼠標右鍵,出現如圖1-4所示的菜單。

圖1-4 建立匯編程序工程之四

(8)    在菜單中選擇“Setting”。彈出另一個對話框,如圖1-5所示。在“Commands”編輯框中輸入“ml /c /coff /Zi test.asm”,在“Outputs”編輯框中輸入“test.obj”。再單擊“OK”。

圖1-5 建立匯編程序工程之五

(9)    最后,再將“ML.EXE”和“ML.ERR”兩個文件復制到“c:"windows”。如果Windows安裝到其他目錄,則需要把這兩個文件復制到相應的目錄。可用“set windir”命令顯示出Windows的安裝目錄。

(10)最后,驗證是否能在VC中編譯test.asm。在VC中按F7鍵,應該自動編譯生成test.exe。如果源程序中有錯誤,編譯后將錯誤信息顯示在“Output”的“Build”視圖中。點擊該錯誤信息,光標自動定位到出現錯誤的程序行(也可以按F4鍵定位到錯誤的程序行)。

為了使VC適合於匯編語言的調試,可對它進行如下設置,如圖1-6所示。

(11)從“Tools”菜單中選擇“Options…”,再選擇“Debug”頁,選中“Disassembly window”中的“Code bytes”(前面打上對勾)。

(12)在“Memory window”中,選中“Fixed width”,在后面填入數字16。

(13)在“General”中,選中“Hexdecimal display”。

(14)不選“View floating point registers”。

圖1-6 VC的調試設置選項

程序編譯成功后,按Ctrl+F5可以運行已編譯好的程序。

1.2.2 匯編程序的調試

一、設置斷點

如果程序運行的結果不正確,可以在VC中調試。單擊“FileView”視圖中的test.asm,這個源程序就會自動地進入VC的編輯窗口。

將光標移動到程序入口所在的程序行上,按F9鍵。就在該行設置了一個斷點。斷點的程序行前有一個紅色的小圓點,如圖1-7所示。

按F5鍵在Debug狀態下執行程序,或者從菜單中選擇“Build”→“Start Debug”→“Go”。

這時,當前窗口顯示出程序中的指令序列,有一個黃色箭頭,它就是程序要執行的下一條指令,如圖1-8所示。

二、內存窗口

從菜單中選擇“View”→“Debug Windows”→“Memory”,打開內存窗口,在地址“Address:”后面的編輯框中可以輸入內存變量的名稱,這里輸入szTitle。內存窗口中就顯示出該變量所在內存單元的值。前面的部分是以十六進制的形式顯示出來的,后面是以ASCII字符的形式顯示出來的。

在內存窗口上單擊鼠標右鍵,可以選擇:按字節、字、雙字顯示內存單元的值。

三、寄存器窗口

從菜單中選擇“View”→“Debug Windows”→“Registers”,打開寄存器窗口。在寄存器窗口中,顯示了各個32位寄存器和段寄存器的值。

在調試程序時,如果某一個寄存器或內存單元的值被改變,則它的值用紅色顯示出來。

在寄存器窗口中的最后一行,顯示的內存單元就是當前指令要讀或寫的操作數。

EFLAGS狀態寄存器的值是按位顯示的。但是,VC並沒有使用我們所熟悉的OF、DF、IF、SF、ZF、AF、PF、CF名稱,而是用它自己的一套名稱,如表1-1所示。

表1-1 VC中的EFLAGS標志位

VC格式

OV

UP

EI

PL

ZR

AC

PE

CY

FLAGS位

OF

DF

IF

SF

ZF

AF

PF

CF

含義

溢出

方向

中斷允許

符號

為零

輔助進位

奇偶

進位

例如UP=0表示DF=0。

四、監視窗口

從菜單中選擇“View”→“Debug Windows”→“Watch”,打開監視窗口。在“Name”一欄下面,可以輸入想要監視的變量或寄存器名稱。監視窗口會隨時將這些變量的值顯示出來。

要在調試過程中改動寄存器或內存變量的值,可以在Watch窗口的該寄存器或變量的內容(在Value列)用鼠標左鍵單擊,修改其值后,按回車鍵即可。

也可以在內存窗口中修改變量的值。在要修改的內存單元上點擊,直接輸入新的內容即可。

另外一種方法是按Shift+F9。彈出對話框后,在“Expression”處輸入寄存器或內存變量的名稱,再在下面的Value一列處修改其內容。最后,按“OK”。

圖1-7 編輯、編譯匯編源程序並設置斷點

圖1-8中為打開內存窗口、監視窗口和寄存器窗口后的屏幕顯示。

調試過程中,編輯窗口中顯示出匯編源程序。如果要查看程序的實際執行代碼,從菜單中選擇“View”→“Debug Windows”→“Disassmebly”。在運行過程中,實際上運行的是機器代碼,而不是匯編源程序。機器代碼及其反匯編的指令和源程序混合顯示在編輯窗口中。反匯編中的程序地址和指令中的數據都是用十六進制顯示的。在調試過程中,使用十六進制來表示地址和(變量或寄存器的)數值更方便。

按F10鍵可一步一步地執行程序。執行過程中,可以在內存窗口中觀察變量的變化;在寄存器窗口中可以看到寄存器的變化;更加方便的是,可以把鼠標移動到編輯窗口中的寄存器或變量上,停留幾秒鍾后,VC會自動地顯示它們的值。

按Shift+F5鍵,可結束調試。

 

圖1-8 VC調試環境:編輯窗口、內存窗口、監視窗口和寄存器窗口

1.2.3 常用調試命令

常用的調試命令如表1-2所示。

表1-2 VC的常用調試命令

功能鍵

作  用

描  述

F11

單步執行

Step Into

F10

執行

Step Over

Ctrl+F10

執行到當前光標的位置的指令

Run to Cursor

F9

在當前光標的位置的指令上設置/清除斷點

Set/Clear Breakpoint at Cursor

F5

執行程序

Go

Shift+F5

終止程序,退出程序

Stop Debugging

設置當前指令

將光標處的指令設為當前指令

Set Next Statement

Shift+F11

當前子程序執行結束

Step Out

l         F11:單步執行當前指令。當前指令在反匯編窗口中用一個黃色箭頭指示,CS:EIP指向當前指令。按F11鍵后,當前指令執行,黃色箭頭和EIP隨之變化,指向新的當前指令。

l         F10:執行當前進程指令。F10和F11在執行一般指令時沒有區別。在當前指令是一條CALL、INT指令的情況下有所區別。如果當前指令是CALL指令,按F11后,進入到子程序的第一條指令,子程序執行前就進入調試狀態,可調試子程序的執行過程;按F10后,子程序執行完畢后才回到調試狀態,不需要調試子程序的執行過程。

l         Ctrl+F10:先把光標移動到一條指令上,可以用鍵盤上的上、下箭頭移動光標,或者在某一行上點擊。再按Ctrl+F10,程序就從當前指令處開始執行,一直到光標處的指令再停下來。

l         F9:先把光標移動到一條指令上,按F9,就在該指令上設置了一個斷點。再按F9,這個斷點就清除了。設置斷點后,指令的前面標有一個紅色的圓點。程序運行到斷點時,會停下來,這時就可以檢查各個變量、寄存器的內容以及程序的執行流程是否正確,以查找程序中的錯誤。

l         F5:從當前指令開始執行程序,直到遇到斷點或程序結束時為止。

l         Shift+F5:終止程序,不再執行后面的程序。終止后,可以再按F11鍵(或Ctrl+Shift+F5)重新開始調試過程。

l         設置當前指令:在調試時,可能希望跳過一部分程序不執行,也可能想將已執行過的一段程序再執行一遍。這可以通過改變當前指令來實現。在新的當前指令上按下鼠標右鍵,彈出一個菜單,在其中選擇“Set Next Statement”。這時,黃色箭頭就指到新設置的當前指令上。

l         Shift+F11:先按住Shift鍵,再按下F11。當前指令在子程序中時,如果想使整個子程序執行完畢,返回到主程序,則使用Shift+F11。

某些功能也可以從“Debug”菜單中選擇。如圖1-9所示。

圖1-9 VC的部分Debug菜單項

1.3 字符串輸入、輸出

在C語言中,常用printf、scanf、sprintf等函數來實現字符串的的輸入輸出,在匯編語言中,可以調用這些函數。

1. printf

在前面的程序例子中已經用到過printf。在程序中,要指明printf的調用規則,以及它的參數類型。

printf          PROTO C :dword,:vararg

printf使用C調用規則(參數自右至左入棧,由主程序平衡堆棧)。第1個參數是一個雙字(:dword),即字符串的地址,后面的其他參數個數可變,可以1個沒有,也可以跟多個參數。

以下C語句輸出3個整數A、B、R和一個字符Op:

printf ("%d %c %d = %d"n" , A, Op, B, R);

在匯編語言中,在數據區中要定義szOutputFmtStr:

szOutputFmtStr       byte    '%d %c %d = %d', 0ah, 0

使用invoke語句調用printf。Printf后面跟的第1個參數是格式字符串的地址;第2、3、4個參數分別是要輸出的整數。

invoke printf, offset szOutputFmtStr, A, Op, B, R

在程序中,還需要包括以下語句,指示鏈接程序在msvcrt.lib庫文件尋找鏈接信息。

includelib      msvcrt.lib

2. sprintf

sprintf與printf相似,它將輸出保存在第1個字符串szStr中。

invoke sprintf, offset szStr, offset szOutputFmtStr, A, Op, B, R

3. scanf

scanf是從控制台將用戶的輸入讀入到程序的變量中,變量的類型可以是整數、字符、字符串等。

scanf的調用規則和參數類型說明為:

scanf           PROTO C :dword,:vararg

scanf的鏈接信息也包括在msvcrt.lib庫文件中。

程序中需要輸入A、Op、B時,A、B是整數,OP是字符。它的第1個參數是格式字符串的地址;第2、3、4個參數分別是A、Op、B的地址。

szInputFmtStr   byte    '%d %c %d', 0

invoke          scanf,offset szInputFmtStr,offset A,offset Op,offset B

其效果等價於:

scanf("%d %c %d", &A, &Op, &B);

下面的程序首先調用printf顯示字符串,提示用戶輸入要計算的表達式,再調用scanf接收用戶的輸入。根據輸入的運算符Op,通過條件跳轉指令實現對加、減、乘、除的判斷和處理。最后,調用printf輸出計算結果。其執行結果為:

input (a Op b, Op=+-/*, ex: 28-2): 4*5

4 * 5 = 20

;程序清單:equation.asm(四則運算)

.386

.model flat,stdcall

Option casemap:none

includelib      msvcrt.lib

scanf           PROTO C :dword,:vararg

printf          PROTO C :dword,:vararg

.data

szInPmt         byte    'input (a Op b, Op=+-/*, ex: 28-2): ', 0 ;

szInputFmtStr   byte    '%d %c %d', 0

szOutputFmtStr byte    '%d %c %d = %d', 0ah, 0

szErrMsg        byte    'invalid Operation. ', 0ah, 0

A               sdword ?

B               sdword ?

Op              dword   ?

R               sdword ?

.code

start:

                invoke printf, offset szInPmt

                invoke scanf, offset szInputFmtStr,

                        offset A,

                        offset Op,

                        offset B

                mov     eax, A

                mov     ebx, B

                cmp     Op, '+'

                jz      lab_add

                cmp     Op, '-'

                jz      lab_sub

                cmp     Op, '*'

                jz      lab_mul

                cmp     Op, '/'

                jz      lab_div

lab_err:              

                invoke printf, offset szErrMsg

                jmp     lab_exit

lab_add:      

                add     eax, ebx

                mov     R, eax

                jmp     lab_output

lab_sub:      

                sub     eax, ebx

                mov     R, eax

                jmp     lab_output

lab_mul:      

                imul    eax, ebx

                mov     R, eax

                jmp     lab_output

lab_div:      

                cdq

                idiv    ebx

                mov     R, eax

                jmp     lab_output

lab_output:   

                invoke printf, offset szOutputFmtStr, A, Op, B, R

lab_exit:     

                ret

end             start

equation.asm在C:"asm"sample"chap-01目錄中,編譯連接的步驟為:

(1) 進入C:"asm"sample"chap-01目錄

cd C:"asm"sample"chap-01

(2) 設置編譯環境

c:"asm"bin"asmvars.bat

(3) 編譯連接

ml /coff equation.asm /link /subsystem:console

1.4 常用Windows API調用

API是application programming interface的縮寫,代表應用程序編程接口。API一般使用stdcall調用規則。

1. MessageBox

printf和scanf適用於控制台程序(鏈接選項為/subsystem:console),而帶窗口的Windows程序(鏈接選項為/subsystem:windows)不能使用printf和scanf。這里介紹一個輸出信息用的API-MessageBox。

它的調用規則和參數類型說明為:

MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD

MessageBoxA的鏈接信息包括在user32.lib庫文件中。

MessageBoxA的C語言原型在VC附帶的"winuser.h"中提供。

2. 確定函數的聲明語句和庫文件

在編程中,應盡可能地利用已有的C的庫函數和Windows API函數,以減少編程的工作量。

通過查閱在MSDN(或VC等工具)資料和幫助文件、閱讀示例程序等方法,弄清函數的功能以及入口、出口參數,以及每一個參數的用法。根據函數的名稱、參數的個數、類型、調用規則等,寫出這樣的聲明語句:

printf          PROTO C :dword,:vararg

再確定它屬於哪一個庫文件。常用的庫文件有:msvcrt.lib、kernel32.lib、user32.lib等。

函數可能返回的是一個整數、指針或其他類型。無論如何,返回值都在EAX中。要注意有些函數是通過傳遞地址指針的方式來改變參數的值,如scanf。

1.5 讀取CPU標識

CPUID指令是獲得CPU信息的匯編指令,它可以返回CPU類型、型號、制造商信息、商標信息、序列號、緩存等CPU相關信息。

CPUID指令使用eax作為輸入參數,eax、ebx、ecx、edx作為輸出參數。例如:

                mov     eax, 0

                cpuid

執行結果為:EAX = 00000002 EBX = 756E6547 ECX = 6C65746E EDX = 49656E69。結果以十六進制顯示。EBX、ECX、EDX中各存儲4個字符,全部12個字符為:GenuineIntel。

使用eax=3作為輸入參數時,在ECX、EDX中返回CPU序列號的第0~31位、第32~63位。

                mov     eax, 0

                cpuid

;程序清單:cpuid.asm(讀取CPU標識)

.586

.model flat,stdcall

Option casemap:none

includelib      msvcrt.lib

printf          PROTO C :dword,:vararg

.data

szVendorID      byte 13 dup (0)

szFormatStr     byte 'VendorID = %s; Processor SN = %08X%08X', 0ah

.code

start:

                mov     eax, 0

                cpuid

 

                mov     dword ptr szVendorID, ebx

                mov     dword ptr szVendorID+4, edx

                mov     dword ptr szVendorID+8, ecx

               

                mov     eax, 3

                cpuid

 

                invoke printf, offset szFormatStr,

                        offset szVendorID, ecx, edx

 

                ret

end             start

程序運行結果如下所示:

VendorID = GenuineIntel; Processor SN = 00000000007B7040

1.6 WinDbg調試工具

WinDbg是微軟公司發布的免費源碼級調試工具。Windbg可以用於Kernel模式調試和用戶模式調試,還可以調試Dump文件。

使用WinDbg調試匯編程序的主要步驟為:

1.首先,使用下面的命令編譯、鏈接,產生.EXE文件。/coff選項要求MASM生成鏈接器所需要的COFF格式的.obj文件,/Zi則指定編譯生成的目標文件中含有調試信息,/link表示要生成.EXE文件,而/subsystem:console則表示生成控制台程序。

ml /coff /Zi cpuid.asm /link /subsystem:console

2.啟動WinDbg,從菜單File→Open Executable裝入.EXE文件。

3.在WinDbg命令窗口的最下方,可輸入命令,按回車鍵執行。如:

x cpuid!

在窗口內顯示出cpuid.exe內的所有數據變量:

0:000> x cpuid!

*** WARNING: Unable to verify checksum for cpuid.exe

00404000 cpuid!szVendorID = 0x00 ''

0040400d cpuid!szFormatStr = 0x56 'V'

4.輸入u命令,可以查看匯編指令:

0:000> u start l e

cpuid!start [cpuid.asm @ 11]:

00401010 b800000000      mov     eax,0

00401015 0fa2            cpuid

00401017 891d00404000 mov     dword ptr [cpuid!szVendorID (00404000)],ebx

0040101d 891504404000 mov     dword ptr [cpuid!szVendorID+0x4 (00404004)],edx

00401023 890d08404000 mov     dword ptr [cpuid!szVendorID+0x8 (00404008)],ecx

00401029 b803000000      mov     eax,3

0040102e 0fa2            cpuid

00401030 52              push    edx

00401031 51              push    ecx

00401032 6800404000      push    offset cpuid!szVendorID (00404000)

00401037 680d404000      push    offset cpuid!szFormatStr (0040400d)

0040103c e811000000      call    cpuid!printf (00401052)

00401041 83c410          add     esp,10h

00401044 c3              ret

5.輸入bp命令,可以設置斷點,例如:

bp start

6.從菜單中選擇Debug→Go,或者按F5鍵,可以執行到斷點處。

7.從菜單中選擇View→Disassembly,可以看到斷點處的指令以高亮方式顯示。

8.從菜單中選擇View→Register,打開一個窗口,顯示寄存器的當前值。

9.在WinDbg命令窗口輸入r命令,也可以顯示寄存器的當前值。還可以修改寄存器的值,如“r eax=5”。

10.在WinDbg命令窗口輸入輸入d命令,可以查看內存內容,如:“d szVendorID L c”。將d換為db、dw、dd,則指定用字節、字、雙字的格式查看。L后面跟的數字則表示查看的單元個數。

11.按F11、F10、Shift+F11、Ctrl+F10分別表示單步執行當前指令、執行完畢當前指令、執行完當前函數、執行到光標處,其用法與表1-2相同。

1.7 實驗題:用MessageBox函數顯示CPU信息

cpuid.asm采用的是控制台模式(鏈接選項為/subsystem:console),調用printf輸出信息。

要求:

1.    使用VC 6.0建立工程文件;

2.    采用帶窗口的Windows程序(鏈接選項為/subsystem:windows);

3.    使用sprintf 、MessageBoxA函數;

4.    輸出制造商信息、序列號;

5.    輸出CPU商標信息,執行CPUID的輸入參數為80000002H、80000003H、80000004H,具體格式可查閱CPU指令手冊。

運行結果如圖1-10所示:


免責聲明!

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



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