VC++中开发汇编语言(转)

  1. 汇编程序结构
    1. 一个显示字符串的汇编程序
    2. 程序格式
      1. 1、模式定义
      2. 2、includelib语句
      3. 3、函数声明语句
      4. 4、数据和代码部分
    3. Visual C/C++环境
      1. 创建工程
      2. 汇编程序的调试
        1. 1、设置断点
        2. 2、内存窗口
        3. 3、寄存器窗口
        4. 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++做为开发调试环境。windows

1.1 汇编程序结构

和其余语言同样,汇编语言的源程序也要符合必定的格式,才能被编译程序所识别和处理。学习和掌握这些格式,是进行汇编编程的第一步。缓存

1.1.1 一个显示字符串的汇编程序

       下面是一个简单的汇编程序。sass

;程序清单:test.asm(在控制台上显示一个字符串)app

.386函数

.model flat, stdcall工具

option casemap:none学习

; 说明程序中用到的库、函数原型和常量ui

includelib      msvcrt.libspa

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中,以分号(;)开始的行是注释行。注释行对程序的编译和执行没有影响。

1、模式定义

程序的第一部分是有关模式定义的3条语句:

.386

.model flat, stdcall

option casemap:none

这些语句定义了程序使用的指令集、工做模式。

(1)指令集

.386语句是汇编语言的伪指令,说明本程序使用的指令集是哪种CPU的。还可使用:.808六、.18六、.28六、.38六、.386p、.48六、.486p、.58六、.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”,不然在调用函数的时候会出现问题。

2、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文件,不须要导入库。

3、函数声明语句

对于全部要用到的库函数(或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

4、数据和代码部分

程序中的数据部分和代码部分是分开定义的,数据部分从这一行开始:

.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 汇编程序的调试

1、设置断点

若是程序运行的结果不正确,能够在VC中调试。单击“FileView”视图中的test.asm,这个源程序就会自动地进入VC的编辑窗口。

将光标移动到程序入口所在的程序行上,按F9键。就在该行设置了一个断点。断点的程序行前有一个红色的小圆点,如图1-7所示。

按F5键在Debug状态下执行程序,或者从菜单中选择“Build”→“Start Debug”→“Go”。

这时,当前窗口显示出程序中的指令序列,有一个黄色箭头,它就是程序要执行的下一条指令,如图1-8所示。

2、内存窗口

从菜单中选择“View”→“Debug Windows”→“Memory”,打开内存窗口,在地址“Address:”后面的编辑框中能够输入内存变量的名称,这里输入szTitle。内存窗口中就显示出该变量所在内存单元的值。前面的部分是以十六进制的形式显示出来的,后面是以ASCII字符的形式显示出来的。

在内存窗口上单击鼠标右键,能够选择:按字节、字、双字显示内存单元的值。

3、寄存器窗口

从菜单中选择“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。

4、监视窗口

从菜单中选择“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个参数是格式字符串的地址;第二、三、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个参数是格式字符串的地址;第二、三、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.按F十一、F十、Shift+F十一、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所示:

相关文章
相关标签/搜索