NASM源代码分析—参数分析

来源:互联网 发布:嫁不出去知乎 编辑:程序博客网 时间:2024/06/10 03:20

NASM源代码分析—参数分析

      通过输入nasm –h可以看到NASM的参数介绍。如图:

从图可以看出NASM包括了很多参数,比如

-o:用于指定输出文件

-f:用于指定输出文件格式

-e:指示NASM只进行预处理而不进行汇编。

那么这些参数在源代码中是怎么实现的呢?

 

NASM中,参数分析主要由函数parse_cmdline(int argc, char **argv)process_arg()来处理。

parse_cmdlineNASM主函数nasm.c/main(int argc, char **argv)调用,parse_cmdline的参数和main的参数是一样的。int argc 表示参数的个数(nasm本身也算是一个参数),例如在命令行下输入:

 nasm a.asm –o a.bin

那么此时的参数个数是4,即argc=4

argv就是指向这4个参数的字符串指针。即

argv[0] = “nasm”

argv[1] = ”a.asm”

argv[2] = “-o”

argv[3] = “a.bin”

 

了解了这里,我们来看看parse_cmdline的具体实现:

nasm.c/parse_cmdline(int argc, char **argv)

static void parse_cmdline(int argc, char **argv)

{

    FILE *rfile;

    char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;

    char separator = ' ';

    *inname = *outname = *listname = '/0';

    envreal = getenv("NASM");

    arg = NULL;

    if (envreal)                                                              1

       {     envcopy = nasm_strdup(envreal);

              p = envcopy;

              if (*p && *p != '-')

                     separator = *p++;

      

              while (*p)

              {     q = p;

                     while (*p && *p != separator) p++;

                     while (*p == separator) *p++ = '/0';

 

                     prevarg = arg;

                     arg = q;

                     if (process_arg (prevarg, arg))

                            arg = NULL;

              }

              if (arg)

                     process_arg (arg, NULL);

              nasm_free (envcopy);

    }

 

    /*

     * Now process the actual command line.

     */

    while (--argc)                                                  2

    {

              int i;

              argv++;

              if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@')

              {

                     if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i)))

                            if ((rfile = fopen(p, "r")))

                            {

                                   process_respfile (rfile);

                                   fclose(rfile);

                            }

                            else

                                   report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,

                                          "unable to open response file `%s'", p);

              }

              else

                     i = process_arg (argv[0], argc > 1 ? argv[1] : NULL);

 

              argv += i, argc -= i;

    }

 

    if (!*inname)

              report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,

                              "no input file specified");

}

 

整个函数可以看做两个部分:

第一部分:(1)标号的if结构,这部分通过提取于NASM有关的环境变量作为它的参数。

第二部分:(2)标号的while结构,这部分通过分析的参数来自在命令行输入部分。

 

两部分对参数的分析方法是一样的,我们只看第二部分。

从源代码可以看出,对来自参数命令行的参数,将它们分为两类,一类是参数 -@, 一类为其他。

参数-@ 表示,将NASM的命令行输入到一个文件中,然后通过调用这个文件来执行nasm.例如文件parse.txt的内容为

helloworld.asm –f bin –o helloworld.com

则执行

nasm -@ parse.txt

相当于执行

       nasm helloworld.asm –f bin –o helloworld.com

效果是一样的。而且-@还可以是多行的,方便编译。

       对参数-@的分析是通过函数process_respfile实现的,其实质是从-@后的目标文件中提取字符串,然后通过函数process_arg处理。其余代码都是怎么从变量argv中分析出参数来,没什么可说的。

 

       函数process_respfile的本质是从-@后面指定的文件中提取指令,然后再用process_arg处理,所以下面只具体讨论函数process_arg

在此之前,我们先要说明一下参数的使用方法。

NASM中,有些参数是带选项的,有些没有。

比如:参数-e是不带选项的,而参数-o带选项,即其后面一项是-o的说明,比如-o file.out, 说明file.out是对-o的说明,表示输出文件是file.out

同时还有一种情况是同样是带选项参数比如-o,由两种表示方式,一种是和选项连写,一种是分开写,所以写法:

-ofile.out –o  file.out 的效果是一样的。

 

函数文件头:

static int process_arg (char *p, char *q);

变量p:第一个参数

变量qp后面一个的参数

例如: nasm hello.asm –f elf –o hello

如果p=-f”, q=elf”。

功能:每次处理一组参数,比如不带选项的-e是一组参数,

         带选项的比如“-o hello” -ohello”也是一组参数。

 

步骤:1.判断p的首字母是否是‘-’(一组参数的首字母必以“-”开头)

         2.根据p的第2字符判断参数种类,用switch...case...语句分别处理:

 

一个用到很多的函数:

get_param(p,q,&advance)

       功能:返回参数的选项,

返回值几种情况:

1.如果参数不带选项,例如“-e”则返回NULL

2.如果参数带选项,且选项和参数连写,例如“-ofile.out”,p=-ofile.out,则返回“file.out”。

3.如果参数带选项,且参数于选项不连写,例如“-o file.out,p=-o”, q=file.out”,也返回“file.out”。

 

       advance值:参数带选项且分开写时,advance=1;否则advance=0

 

       其他具体的参数解析情况,只要通过输入“nasm –h”看一下基本就可以明白,没什么大的难度了。

原创粉丝点击