调试工具之GDB

简介

GDB(GNU debugger)是GNU开源组织发布的一个强大的UNIX下的程序调试工具。可以使用它通过命令行的方式调试程序。它使你能在程序运行时观察程序的内部结构和内存的使用情况。你也可以使用它分析程序崩溃前的发生了什么,从而找出程序崩溃的原因。相对于windows下的图形界面的VC等调试工具,它提供了更强大的功能。如果想在Windows下使用gdb,需要安装MinGW或者CygWin,并且需要配置环境变量才可以使用。

一般来说,gdb完成以下四个方面的工作:

1、启动你的程序,修改一些东西,从而影响程序运行的行为。

2、可以指定断点。程序执行到断点处会暂停执行。

3、当你的程序停掉时,你可以用它来观察发生了什么事情。

4、动态的改变你程序的执行环境,尝试修正bug。

安装

在安装gdb之前,先确定你的linux操作系统是否安装了gdb。你可以使用如下命令来确定是否安装了gdb。


1

#gdb -help

如果已经安装了gdb,那么将会显示它能使用的所有参数。如果没有安装,我们可以通过以下几种方式来安装。

通过yum命令安装

通过yum安装的命令行如下:


1

#yum install gdb

通过rpm包方式安装

从http://rpmfind.net/linux/rpm2html/search.php?query=gdb上下载合适的rpm安装包。假如我们下载的安装名称为gdb-7.8.1.rpm。然后通过如下命令安装。


1

#rpm -ivh ./gdb-7.8.1.rpm

通过源码方式安装

安装gdb是很容易的。只要按照以下步骤一步步操作即可。

1、但是安装之前,必须保证它所依赖的环境没问题。下面是它依赖的依赖环境。

* c语言编译器。推荐使用gcc。

* 确保有不少于150M的磁盘空间。

2、然后打开这个网址 ftp://sourceware.org/pub/gdb/releases/,下载需要安装的gdb源码包。我们下载的源码包是gdb-7.8.1.tar.gz。

3、解压压缩包。压缩包解压结束后,进入解压后的目录。


1

2

3

#gzip -d gdb-7.8.1.tar.gz

#tar xfv gdb-7.8.1.tar.gz

#cd gdb-7.8.1

4、然后一次执行如下命令,以便完成安装


1

2

3

#./configure

#make

#make install

基本使用

命令行格式

gdb    [-help] [-nx] [-q] [-batch] [-cd=dir] [-f] [-b bps] [-tty=dev] [-s symfile] [-e prog] [-se prog] [-c core] [-x

              cmds] [-d dir] [prog[core|procID]]

常用功能介绍

网上的一些教程基本上都是介绍使用gdb调试c或者c++语言编写的程序的。我们这节主要说明如何使用gdb调试php程序。我们的php脚本如下:
文件名为test.php,代码如下:


1

2

3

4

5

6

<?php

echo "hello \n";

for($i = 0; $i < 10; $i++){    

    echo $i."\n";    

    sleep(10); }

?>

启动gdb

启动gdb可以使用如下几种方式:

第一种方式:

启动的时候指定要执行的脚本。


1

2

3

4

5

6

7

#sudo gdb /usr/bin/php

......

Reading symbols from /home/fpm-php5.5.15/bin/php...done.

(gdb) set args ./test.php

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

......

启动的时候指定php程序的路径。
Reading symbols from /home/fpm-php5.5.15/bin/php...done. 说明已经加载了php程序的符号表。
使用set args 命令指定php命令的参数。
使用r命令开始执行脚本。r即为run的简写形式。也可以使用run命令开始执行脚本。

第二种方式:
启动后通过file命令指定要调试的程序。当你使用gdb调试完一个程序,想调试另外一个程序时,就可以不退出gdb便能切换要调试的程序。具体操作步骤如下:


1

2

3

4

5

6

7

8

9

#sudo gdb ~/home/test/exproxy

......

Reading symbols from /home/hailong.xhl/exproxy/test/exproxy...(no debugging symbols found)...done.

(gdb) file /home/fpm-php/bin/php

Reading symbols from /usr/bin/php...done.

(gdb) set args ./test.php

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

......

上面的例子中我们先使用gdb加载了程序exproxy进行调试。然后通过file命令加载了php程序,从而切换了要调试的程序。

获取帮助信息

gdb的子命令很多,可能有些你也不太熟悉。没关系,gdb提供了help子命令。通过这个help子命令,我们可以了解指定子命令的一些用法。如:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#gdb

......

(gdb) help set

Evaluate expression EXP and assign result to variable VAR, using assignment

syntax appropriate for the current language (VAR = EXP or VAR := EXP for

example).  VAR may be a debugger "convenience" variable (names starting

with $), a register (a few standard names starting with $), or an actual

variable in the program being debugged.  EXP is any valid expression.

Use "set variable" for variables with names identical to set subcommands.

 

With a subcommand, this command modifies parts of the gdb environment.

You can see these environment settings with the "show" command.

 

List of set subcommands:

 

set annotate -- Set annotation_level

set architecture -- Set architecture of target

set args -- Set argument list to give program being debugged when it is started

.......

(gdb) help set args

Set argument list to give program being debugged when it is started.

Follow this command with any number of args, to be passed to the program.

......

可见,通过help命令,我们可以了解命令的功能和使用方法。如果这个子命令还有一些子命令,那么它的所有子命令也会列出来。如上,set命令的set args等子命令也都列出来了。你还可以使用help命令来了解set args的更详尽的信息。

设置断点

为什么要设置断点呢?设置断点后,我们就可以指定程序执行到指定的点后停止。以便我们更详细的跟踪断点附近程序的执行情况。
设置断点的命令是break,缩写形式为b。
设置断点有很多方式。下面我们举例说明下常用的几种方式。
根据文件名和行号指定断点
如果你的程序是用c或者c++写的,那么你可以使用“文件名:行号”的形式设置断点。示例如下:


1

2

3

4

5

6

7

8

9

10

11

12

#gdb /usr/bin/php

(gdb) set  args ./test.php

(gdb) b basic_functions.c:4439

Breakpoint 6 at 0x624740: file /home/php-5.5.15/ext/standard/basic_functions.c, line 4439.

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

hello

0

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

(gdb)

示例中的(gdb) b basic_functions.c:4439 是设置了断点。断点的位置是basic_functions.c文件的4439行。使用r命令执行脚本时,当运行到4439行时就会暂停。暂停的时候会把断点附近的代码给显示出来。可见,断点处是zif_sleep方法。这个zif_sleep方法就是我们php代码中sleep方法在php内核中的实现。根据规范,php内置提供的方法名前面加上zif_,就是这个方法在php内核或者扩展中实现时定义的方法名。

根据文件名和方法名指定断点
有些时候,手头没有源代码,不知道要打断点的具体位置。但是我们根据php的命名规范知道方法名。如,我们知道php程序中调用的sleep方法,在php内核中实现时的方法名是zif_sleep。这时,我们就可以通过"文件名:方法名"的方式打断点。示例如下:


1

2

3

4

5

6

7

8

9

10

11

12

#gdb /usr/bin/php

(gdb) set  args ./test.php

(gdb) b basic_functions.c:zif_sleep

Breakpoint 6 at 0x624740: file /home/php-5.5.15/ext/standard/basic_functions.c, line 4439.

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

hello

0

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

(gdb)

另外,如果你不知道文件名的话,你也可以只指定方法名。命令示例如下:


1

2

3

......

(gdb)b zif_sleep

......

设置条件断点
如果按上面的方法设置断点后,每次执行到断点位置都会暂停。有时候非常讨厌。我们只想在指定条件下才暂停。这时候根据条件设置断点就有了用武之地。设置条件断点的形式,就是在设置断点的基本形式后面增加 if条件。示例如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

......

(gdb) b zif_sleep if num > 0

Breakpoint 9 at 0x624740: file /home/php_src/php-5.5.15/ext/standard/basic_functions.c, line 4439.

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

hello

0

 

Breakpoint 9, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

(gdb)

......

查看断点
可以使用info breakpoint查看断点的情况。包含都设置了那些断点,断点被命中的次数等信息。示例如下:


1

2

3

4

5

6

7

8

......

(gdb) info breakpoint

Num     Type           Disp Enb Address            What

9       breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

    stop only if num > 0

    breakpoint already hit 1 time

10      breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

......

删除断点
对于无用的断点我们可以删除。删除的命令格式为 delete breakpoint 断点编号。info breakpoint命令显示结果中的num列就是编号。删除断点的示例如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

......

(gdb) info breakpoints

Num     Type           Disp Enb Address            What

9       breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

    stop only if num > 0

    breakpoint already hit 1 time

10      breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

(gdb) info breakpoint

Num     Type           Disp Enb Address            What

9       breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

    stop only if num > 0

    breakpoint already hit 1 time

10      breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

(gdb) delete 9

(gdb) info breakpoint

Num     Type           Disp Enb Address            What

10      breakpoint     keep y   0x0000000000624740 in zif_sleep at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

(gdb)

......

上面的例子中我们删除了编号为9的断点。

查看代码

断点设置完后,当程序运行到断点处就会暂停。暂停的时候,我们可以查看断点附近的代码。查看代码的子命令是list,缩写形式为l。显示的代码行数为10行,基本上以断点处为中心,向上向下各显示几行代码。示例代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

#gdb /usr/bin/php

(gdb) set  args ./test.php

(gdb) b basic_functions.c:zif_sleep

Breakpoint 6 at 0x624740: file /home/php-5.5.15/ext/standard/basic_functions.c, line 4439.

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

hello

0

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

(gdb)l

4434    /* }}} */

4435   

4436    /* {{{ proto void sleep(int seconds)

4437       Delay for a given number of seconds */

4438    PHP_FUNCTION(sleep)

4439    {

4440        long num;

4441   

4442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {

4443            RETURN_FALSE;

另外,你可以可以通过指定行号或者方法名来查看相关代码。
指定行号查看代码示例:


1

2

3

4

5

6

7

8

9

10

11

12

13

......

(gdb) list 4442

4437       Delay for a given number of seconds */

4438    PHP_FUNCTION(sleep)

4439    {

4440        long num;

4441   

4442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {

4443            RETURN_FALSE;

4444        }

4445        if (num < 0) {

4446            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of seconds must be greater than or equal to 0");

......

指定方法名查看代码示例:


1

2

3

4

5

6

7

8

9

10

11

12

13

......

(gdb) list zif_sleep

4434    /* }}} */

4435   

4436    /* {{{ proto void sleep(int seconds)

4437       Delay for a given number of seconds */

4438    PHP_FUNCTION(sleep)

4439    {

4440        long num;

4441   

4442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {

4443            RETURN_FALSE;

......

单步执行

断点附近的代码你了解后,这时候你就可以使用单步执行一条一条语句的去执行。可以随时查看执行后的结果。单步执行有两个命令,分别是step和next。这两个命令的区别在于:
step 一条语句一条语句的执行。它有一个别名,s。
next 和step类似。只是当遇到被调用的方法时,不会进入到被调用方法中一条一条语句执行。它有一个别名n。
可能你对这两个命令还有些迷惑。下面我们用两个例子来给你演示下。
step命令示例:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#gdb /usr/bin/php

(gdb) set  args ./test.php

(gdb) b basic_functions.c:zif_sleep

Breakpoint 6 at 0x624740: file /home/php-5.5.15/ext/standard/basic_functions.c, line 4439.

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

hello

0

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

.......

(gdb) s

4442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {

(gdb) s

zend_parse_parameters (num_args=1, type_spec=0x81fc41 "l") at /home/php_src/php-5.5.15/Zend/zend_API.c:917

917 {

可见,step命令进入到了被调用函数中zend_parse_parameters。使用step命令也会在这个方法中一行一行的单步执行。

next命令示例:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#gdb /usr/bin/php

(gdb) set  args ./test.php

(gdb) b basic_functions.c:zif_sleep

Breakpoint 6 at 0x624740: file /home/php-5.5.15/ext/standard/basic_functions.c, line 4439.

(gdb) r

Starting program: /home/fpm-php5.5.15/bin/php ./test.php

hello

0

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

.......

(gdb) n

4442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {

(gdb) n

4445        if (num < 0) {

可见,使用next命令只会在本方法中单步执行。

继续执行

run命令是从头开始执行,如果我们只是想继续执行就可以使用continue命令。它的作用就是从暂停处继续执行。命令的简写形式为c。继续执行过程中遇到断点或者观察点变化依然会暂停。示例代码如下:


1

2

3

4

5

6

7

8

9

......

(gdb) c

Continuing.

6

 

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

......

查看变量

现在你已经会设置断点,查看断点附近的代码,并可以单步执行和继续执行。接下来你可能会想知道程序运行的一些情况,如查看变量的值。print命令正好满足了你的需求。使用它打印出变量的值。print命令的简写形式为p。示例代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

......

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

......

(gdb) n

4442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {

(gdb) n

4445        if (num < 0) {

(gdb) print num

$1 = 10

(gdb)

......

打印出的num的值为10,正好是我们在php代码中调用sleep方法传的值。另外可以使用“print/x my var” 的形式可以以十六进制形式查看变量值。

设置变量

使用print命令查看了变量的值,如果感觉这个值不符合预期,想修改下这个值,再看下执行效果。这种情况下,我们该怎么办呢?通常情况下,我们会修改代码,再重新执行代码。使用gdb的set命令,一切将变得更简单。set命令可以直接修改变量的值。示例代码如下:


1

2

3

4

5

6

7

8

9

10

11

......

Breakpoint 1, zif_sleep (ht=1, return_value=0x7ffff425a398, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)

    at /home/php_src/php-5.5.15/ext/standard/basic_functions.c:4439

4439    {

......

(gdb) print num

$4 = 10

(gdb) set num = 2

(gdb) print num

$5 = 2

......

上面的代码中我们是把sleep函数传入的10改为了2。即,sleep 2秒。注意,我们示例中修改的变量num是局部变量,只能对本次函数调用有效。下次再调用zif_sleep方法时,又会被设置为10。

设置观察点

设置观察点的作用就是,当被观察的变量发生变化后,程序就会暂停执行,并把变量的原值和新值都会显示出来。设置观察点的命令是watch。示例代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

......

(gdb) watch num

Hardware watchpoint 3: num

(gdb) c

Continuing.

Hardware watchpoint 3: num

 

Old value = 1

New value = 10

0x0000000000713333 in zend_parse_arg_impl (arg_num=1, arg=0x7ffff42261a8, va=0x7fffffffaf70, spec=0x7fffffffaf30, quiet=0)

    at /home/php_src/php-5.5.15/Zend/zend_API.c:372

372                         *p = Z_LVAL_PP(arg);

(gdb)

......

上例中num值从1变成了10时,程序暂停了。需要注意的是,你的程序中可能有多个同名的变量。那么使用watch命令会观察那个变量呢?这个要依赖于变量的作用域。即,在使用watch设置观察点时,可以直接访问的变量就是被观察的变量。

其他有用的命令

backtrace 简写形式为bt。查看程序执行的堆栈信息。

finish 执行到当前函数的结束。

时间: 2024-10-02 23:37:48

调试工具之GDB的相关文章

每天学点GDB(一)

<一>简单示例--Hello World 在Linux环境下进行C或是C++编程,调试工具首选GDB. GDB的功能很多,一下子全弄明白似乎不太可能.那么就从最简单的使用说起吧.一谈起简单,Helloworld就成了最佳的选择了. #include <stdio.h> #include <stdlib.h> 4 int main(int argc, char** argv) { printf("hello,world\n"); return 0; }

eclipse启动项目时遇到问题,报错!

问题描述 eclipse启动项目时遇到问题,报错! FATAL ERROR in native method: JDWP No transports initialized, jvmtiError=AGENT_ERROR_TRANSPORT_INIT(197) ERROR: transport error 202: connect failed: Connection timed out ERROR: JDWP Transport dt_socket failed to initialize,

万字实录:从DDCTF大赛看当前网络安全新趋势 | 硬创公开课总结文+视频(上篇)

  如果说,滴滴出行(以下简称滴滴)是近几年来让大家出行发生翻天覆地变化的一家公司,想必你不会反对. 据滴滴给出的官方数据,滴滴全平台上每天超过2000万订单.与此而来的是,这么多乘客的消费数据和个人信息,滴滴怎么守护? 快速增长的滴滴意识到了这一点.2016年9月底,硅谷安全教父弓峰敏与网络安全资深专家卜峥加盟滴滴,弓峰敏出任滴滴信息安全战略副总裁和滴滴研究院副院长,负责制定信息安全战略和研发下一代信息安全技术,卜峥则担任滴滴信息安全副总裁,全面领导信息安全团队.今年3月9日,滴滴又宣布在加利

linux下C++开发工具

就C++开发工具而言,与Windows下微软(VC, VS2005等)一统天下相比,Linux/Unix下C++开发,可谓五花八门,各式各样.Emacs, vi, eclipse, anjuta,kdevelop等层出不穷.Windows下,开发工具多以集成开发环境IDE的形式展现给最终用户.例如,VS2005集成了编辑器,宏汇编ml,C /C++编译器cl,资源编译器rc,调试器,文档生成工具, nmake.它们以集成方式提供给最终用户,对于初学者而言十分方便.但是,这种商业模式,直接导致用户

gdbserver远程调试嵌入式linux应用程序方法

此处所讲的是基于gdb和gdbsever的远程调试方法.环境为:PC机:win7.虚拟机:10.04.下位机:飞嵌TE2440开发板.   嵌入式linux应用程序的开发一般都是在linux里面编写好代码,并用交叉编译器arm-linux-gcc编译好之后再下载到板子上运行.如果建立了远程调试(能够在PC机ubuntu中调试板子中的linux应用程序),这样对于开发程序是极其方便的.   以下是摘自网络上的一些方法.其中加入了自己所遇到的一些问题,并提出了解决方法.   1.首先建立nfs文件系

Docker到底是什么?Docker为什么它这么火!_docker

Xcode 是运行在操作系统Mac OS X上的集成开发工具(IDE),由苹果公司开发.Xcode是开发OS X 和 iOS 应用程序的最快捷的方式.Xcode 具有统一的用户界面设计,编码.测试.调试都在一个简单的窗口内完成. 背景介绍 Xcode前身是继承自NeXT的Project Builder. The Xcode suite 包含有GNU Compiler Collection自由软件 (GCC. apple-darwin9-gcc-4.0.1 以及 apple-darwin9-gcc

Linux系统中的gdb程序调试工具的命令知识介绍

在Linux系统中有许多的命令程序来辅助系统的正常和方便运行,那么其中在系统中有着一个叫做gdb命令的程序,那么我们今天就来了解下关于gdb命令的知识吧! 一.常规调试 gdb是Linux下常用的程序调试工具,当然前提是用gcc/g++编译时加上-g参数,这样编译出的可执行程序会加上gdb调试信息. gdb命令不少,但常用的主要包括如下命令: (1)list [file:]functuon 命令缩写是l,查看源码,不加参数时,向下显示源码,加参数-l时,向上显示源码,默认显示10行. 也可以设置

进程控制-进程都有自己独立的栈,那为什么gdb等调试工具可以修改其他进程栈里的变量值

问题描述 进程都有自己独立的栈,那为什么gdb等调试工具可以修改其他进程栈里的变量值 如题 进程都有自己独立的栈,那为什么gdb等调试工具可以修改其他进程栈里的变量值 解决方案 可以跨进程访问内存,也可以通过注入线程的方法给进程添加代码对于windows来说,前者用ReadMemoryProcess,后者用CreateRemoteThread

《Linux 高级程序设计(第三版)》——2.2 GCC/GDB编译调试工具基础

2.2 GCC/GDB编译调试工具基础 Linux 高级程序设计(第三版) GCC/G++是GNU最优秀的自由软件之一,它主要提供C/C++程序的编译工作.Linux下的C.C++程序开发过程中,一般都采用GCC/G++/GDB工具.将C语言程序编译成一个可执行文件一般都需经过以下4个步骤. (1)预处理(Preprocessing):对源代码文件中的文件包含.宏定义.预编译语句进行分析和替换. (2)编译(Compilation):根据编译器的语法规则,将高级语言转换为以.s为后缀的汇编语言文