• 四川郎酒股份有限公司获第十二届人民企业社会责任奖年度环保奖 2019-05-13
  • 银保监会新规剑指大企业多头融资和过度融资 2019-05-12
  • 韩国再提4国联合申办世界杯 中国网友无视:我们自己来 2019-05-11
  • 中国人为什么一定要买房? 2019-05-11
  • 十九大精神进校园:风正扬帆当有为 勇做时代弄潮儿 2019-05-10
  • 粽叶飘香幸福邻里——廊坊市举办“我们的节日·端午”主题活动 2019-05-09
  • 太原设禁鸣路段 设备在测试中 2019-05-09
  • 拜耳医药保健有限公司获第十二届人民企业社会责任奖年度企业奖 2019-05-08
  • “港独”没出路!“梁天琦们”该醒醒了 2019-05-07
  • 陈卫平:中国文化内涵包含三方面 文化复兴表现在其中 2019-05-06
  • 人民日报客户端辟谣:“合成军装照”产品请放心使用 2019-05-05
  • 【十九大·理论新视野】为什么要“建设现代化经济体系”?   2019-05-04
  • 聚焦2017年乌鲁木齐市老城区改造提升工程 2019-05-04
  • 【专家谈】上合组织——构建区域命运共同体的有力实践者 2019-05-03
  • 【华商侃车NO.192】 亲!楼市火爆,别忘了买车位啊! 2019-05-03
    • / 14
    • 下载费用:30 金币  

    重庆时时彩合买群: 一种面向可变参函数的编译实现方法.pdf

    关 键 词:
    一种 面向 可变 函数 编译 实现 方法
      专利查询网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    摘要
    申请专利号:

    CN201410173673.7

    申请日:

    2014.04.28

    公开号:

    CN103942083A

    公开日:

    2014.07.23

    当前法律状态:

    授权

    有效性:

    有权

    法律详情: 授权|||实质审查的生效IPC(主分类):G06F 9/45申请日:20140428|||公开
    IPC分类号: G06F9/45 主分类号: G06F9/45
    申请人: 中国人民解放军国防科学技术大学
    发明人: 王霁; 孙海燕; 阳柳; 张雪萌; 陈书明; 郭阳; 刘衡竹; 陈跃跃; 龚国辉; 李灿; 陈伟业
    地址: 410073 湖南省长沙市砚瓦池正街47号中国人民解放军国防科学技术大学计算机学院微电子与微处理器研究所
    优先权:
    专利代理机构: 湖南兆弘专利事务所 43008 代理人: 周长清
    PDF完整版下载: PDF下载
    法律状态
    申请(专利)号:

    CN201410173673.7

    授权公告号:

    ||||||

    法律状态公告日:

    2017.10.17|||2014.08.20|||2014.07.23

    法律状态类型:

    授权|||实质审查的生效|||公开

    摘要

    本发明公开一种面向可变参函数的编译实现方法,步骤为:1)获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数存放位置;2)读取函数中参数,判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递;3)从第一个可变参数开始遍历参数,根据参数的存放位置获取参数并根据参数大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。本发明具有实现方法简单、操作便捷、硬件资源利用率高、执行效率高、灵活性强的优点。

    权利要求书

    权利要求书
    1.  一种面向可变参函数的编译实现方法,其特征在于,步骤为:
    (1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;
    (2)参数的传递:读取函数中的参数,根据固定参数个数判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;
    (3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。

    2.  根据权利要求1所述的面向可变参函数的编译实现方法,其特征在于,所述步骤(1)的具体步骤为:
    (1.1)获取函数原型中固定参数的个数,并定义一个用于存储参数寄存器编号、通过栈传递的参数的存放地址的va_list结构体;
    (1.2)定义并执行va_start函数,获取第一个可变参数的存放位置,当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;
    (1.3)将va_list结构体中通过栈传递的参数的存放地址初始化为第一个可变参数存放位置前一个存储单元的地址,并将地址值传递给va_arg函数。

    3.  根据权利要求2所述的面向可变参函数的编译实现方法,其特征在于,所述步骤(3)的具体实施方法为:多次执行va_arg函数,遍历并获取可变参数;每次执行va_arg函数时,由va_list结构体中通过栈传递的参数的存放地址得到上一个参数存储的内存地址,并根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址,获取参数后更新va_list结构体中通过栈传递的参数的存放地址为计算得出的当前参数存储的内存地址。

    4.  根据权利要求3所述的面向可变参函数的编译实现方法,其特征在于,所述根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址的具体实施方法为:判断当前参数的参数类型的长度是否超过一个字,若为是,将va_list结构体中通过栈传递的参数的存放地址加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻址方式进行对齐处理后得到当前参数存储的内存地址。

    5.  根据权利要求1~4中任意一项所述的面向可变参函数的编译实现方法,其特征在于,所述步骤(2)的具体步骤为:
    (2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);
    (2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;
    (2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放。

    说明书

    说明书一种面向可变参函数的编译实现方法
    技术领域
    本发明涉及高级语言编译器领域,尤其涉及一种面向可变参函数的编译实现方法。
    背景技术
    可变参函数是一类特殊的函数,其函数声明中除了包含至少一个固定参数以外,还包含尚未确定的其它参数,而在函数中是通过va_list,va_start,va_arg等关键字来实现参数的迭代和查找??杀洳问诟袷交淙胧涑鲋芯哂薪隙嗟挠τ?,编译器在编译这类函数时,由于不知道具体的参数个数,对可变参数的处理方式和普通函数有很大的区别,编译器需要考虑到可能出现的各种情况,如参数的位置,传参的方式等。
    要正确的实现可变参函数的编译有以下两个要点:
    (1)父函数按照正确的规则将参数存放在正确的位置;
    (2)子函数能够按照一定的规则去正确的位置找到所需要的参数;
    这两个要点都和参数传递方式以及栈帧存储方式密切相关,而对于不同的体结构来说,参数传递和存储的方式都不一样,因此编译器需要针对特定的体系结构做特定的处理,才能保证正确编译可变参函数。
    对于可变参函数程序的编译实现,其关键是定义和处理va_list、va_start和va_arg这几个关键字,通常情况下每个上述关键字都需要定义一个相应的函数来进行,这三个关键字所实现的功能分别为:
    va_list关键字: va_list关键字在可变参中所起的作用是定义一个可变参的指针,存储可变参信息,如参数寄存器编号、参数类型以及当前参数存储位置等。va_list可以是一个包含多个成员变量的结构体,也可以仅仅是一个指针变量。
    va_start关键字: va_start关键字所起的作用是对va_list进行初始化,将指针指向第一个可变参所存储的位置(也有可能是第一个可变参之前的那个位置),使得va_arg能够准确定位,将后面的参数逐一的找到。第一个可变参所存储的位置是与栈帧布局息息相关,通?;峤岷掀胀ú问拇砉?,共同决定其存放位置,而不同的可变参编译方法对于这一步的处理方法会有所不同。
    va_arg关键字:va_arg关键字是遍历所有参数,在正确的位置找到相应的可变参数。va_arg在一个程序中可以多次执行,每执行一次,都会获取当前的参数的存储地址,执行完以后,指向当前参数地址的指针会向后面移动,指向下一个参数的位置,以此类推,完成所有可变参数的查找。
    目前对于可变参函数的编译方法中,参数传递方法主要有两种:
    方法1:所有的参数不论是否为可变参,都通过栈来传递,只要计算出是第几个参数,即可获取该参数的存储地址,即可变参数和普通参数处理方法相同。
    方法2:在还有可用的参数寄存器的情况下,可变参函数使用参数寄存器来传递,参数寄存器使用完以后,再通过栈来进行传递,每次变量指针都指向下一个参数的存储位置。
    如图1所示,传统的普通函数参数传递处理方法,其中N为参数寄存器的数目,该数目与体系结构相关,可根据需要定义其大小。进行参数传递时,首先逐个读取参数并计数,如果当前参数的数目小于N,说明还有可用的参数寄存器,当前参数则通过参数寄存器来传递并且将已使用的参数寄存器数目增加1;当前参数数目正好等于N时,说明当前参数寄存器已经使用完,当前参数是最后一个可以通过寄存器来传递的参数;当前参数数目大于N时,参数则全部通过栈来传递。编译器会根据体系结构特点和栈帧布局等来指定一个栈传递参数的存放起始位置,通常情况下是由栈指针加上一个固定大小的偏移量offset来得到该起始位置。确定了起始位置后,就能够确定通过栈传递的第一个参数的位置,后续的参数依次进行传递存储,直到完成整个传参的过程。
    对于方法1,由于没有使用寄存器传参,不能充分的利用寄存器,且全部通过栈来传递加大了内存开销,尤其是将非可变参函数的参数和可变参函数的固定参数也都通过栈来传递,造成很大的空间浪费、降低执行效率,且所有参数采用同样的处理方法进行处理,其灵活性也较差。
    对于方法2,虽然能够充分利用参数寄存器,但是由于可变参函数的可变参无论是数目还是类型都是不固定的,处理过程复杂而繁琐。在计算可以通过参数寄存器来传递的可变参数个数以及通过栈传递剩余参数的个数时,需要考虑许多复杂的情况,如参数有可能是char、int或double类型,甚至为结构体类型,有时参数需要占用一个以上的参数寄存器,这样通过参数寄存器传递的参数数目就会相应的减少。另一方面,每次执行完一次va_arg,变量指针都指向下一个参数的存储位置,通常是在当前参数的位置加一个字的大小得到下一个参数的存储位置,但假如下一个参数所占的大小并非一个字,而是小于或者大于一个字,那么该变量指针还需要进行相应的调整。此类处理方法会将很多冗余繁琐的情况考虑在内,且有可能需要进行一定的调整,大大降低便捷性,不利于实际应用。
    发明内容
    本发明要解决的技术问题就在于:针对现有技术存在的技术问题,本发明提供一种实现方法简单、操作便捷、硬件资源利用率高、执行效率高、灵活性强的面向可变参函数的编译实现方法。
    为解决上述技术问题,本发明提出的技术方案为:
    一种面向可变参函数的编译实现方法,步骤为:
    (1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;
    (2)参数的传递:读取函数中的参数,根据固定参数个数判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;
    (3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。
    作为本发明的进一步改进,所述步骤(1)的具体步骤为:
    (1.1)获取函数原型中固定参数的个数,并定义一个用于存储参数寄存器编号、通过栈传递的参数的存放地址的va_list结构体;
    (1.2)定义并执行va_start函数,获取第一个可变参数的存放位置,当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;
    (1.3)将va_list结构体中通过栈传递的参数的存放地址初始化为第一个可变参数存放位置前一个存储单元的地址,并将地址值传递给va_arg函数。
    作为本发明的进一步改进,所述步骤(3)的具体实施方法为:多次执行va_arg函数,遍历并获取可变参数;每次执行va_arg函数时,由va_list结构体中通过栈传递的参数的存放地址得到上一个参数存储的内存地址,并根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址,获取参数后更新va_list结构体中通过栈传递的参数的存放地址为计算得出的当前参数存储的内存地址。
    作为本发明的进一步改进,所述根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址的具体实施方法为:判断当前参数的参数类型的长度是否超过一个字,若为是,将va_list结构体中通过栈传递的参数的存放地址加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻址方式进行对齐处理后得到当前参数存储的内存地址。
    作为本发明的进一步改进,所述步骤(2)的具体步骤为:
    (2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);
    (2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;
    (2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放。
    与现有技术相比,本发明的优点在于:
    1)本发明将可变参函数中的固定参数和可变参数进行分开处理,固定参数按照一般方法处理,优先通过参数寄存器来传参,而将所有的可变参都通过栈来传递,既有效的利用了参数寄存器、避免了硬件资源的浪费,又能分别对固定参数和可变参数进行不同的处理,执行效率高、硬件资源利用率高且灵活性强。
    2)本发明在参数的查找中,每执行完一次va_arg函数之后当前va_list结构体指针指向的是当前参数的位置,也就是下一个参数所要储存位置的前一个存储单元位置,不论下一个参数是什么类型,都可以方便的找到其对应的存储位置,而不需要根据参数类型进行调整,免去了繁琐的判断、计算参数大小等复杂的步骤,使得编译处理简单便捷、执行效率高。
    附图说明
    图1是传统的普通函数参数传递过程的处理方法流程示意图。
    图2是本实施例一种面向可变参函数的编译实现方法流程示意图。
    图3是本实施例中参数传递方法流程示意图。
    具体实施方式
    以下结合说明书附图和具体优选的实施例对本发明作进一步描述,但并不因此而限制本发明的?;し段?。
    如图2所示,本实施例一种面向可变参函数的编译实现方法,步骤为:
    (1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置的后一个存储单元;
    (2)参数的传递和存储:读取函数中的参数,根据固定参数的个数判断当前参数的类型,若为固定参数,优先通过参数寄存器传递和存储,没有可用的参数寄存器时通过栈进行传递和存储;若为可变参数,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;
    (3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。
    本实施例在可变参函数的传递和存储中,将固定参数和可变参数进行分开处理,固定参数按照一般方法处理,优先通过参数寄存器来传参,而将所有的可变参数都通过栈来传递,既有效的利用了参数寄存器,同时能够避免硬件资源的浪费;在参数的查找过程中,根据当前参数的存放位置及下一个参数的大小更新得到下一个参数的存放位置。
    本实施例中,步骤(1)的具体步骤如下:
    步骤1.1:定义args结构体和varargs结构体两个结构体类型,分别用来存储普通参数信息和可变参数信息;对varargs结构体进行初始化并获取函数原型中参数的个数。
    本实施例中,args结构体和varargs结构体为:
    struct args {
        int nregs;
        int count;
        int incoming_args_size;
    };
    typedef struct
    {
          int named_arg_num;
          int reg_save_num;
          int reg_save_size;
          int stack_save_size;
    } varargs;
    由于可变参函数的参数和普通参数也存在着一定的共性,在处理时需要用到对一般参数的处理,因此需要存储普通参数的信息。本实施例中,args结构体存储普通参数信息,由成员变量nregs存储当前参数所需占用的参数寄存器数量,若当前参数的长度没有超过一个字,则所需占用参数寄存器的数量为一个;若超过一个字,则所需占用参数寄存器的数量为一个以上;由成员变量count存储当前参数为第几个被传递的参数;由成员变量incoming_args_size存储当前参数的大小。
    本实施例中,varargs结构体用来存储可变参数信息,其中成员变量named_arg_num存储函数原型中固定参数的个数,根据固定参数的个数可以确定后续参数传递的处理;成员变量reg_save_num 和 reg_save_size 存储已经通过参数寄存器传递的参数的个数、大??;成员变量stack_save_size则是存储超过参数寄存器数量的固定参数所需占用的空间大小,即当固定参数个数超过参数寄存器的数量时,多出的固定参数通过栈传递时所需占用的空间大小。
    本实施例中,定义结构体后对结构体varargs进行初始化,并获取函数原型中固定参数的个数n,根据函数原型中固定参数的个数确定后续处理,其中对结构体varargs进行初始化为:
    varargs vararg=
      { 0, 0, 0, 0};
    根据上述表达式可知,将varargs结构体中的变量named_arg_num、reg_save_num、reg_save_size及stack_save_size初始化为0。
    步骤1.2:定义va_list结构体指针,指针包含两个域:一个是当前参数寄存器的编号gpr,另一个是通过栈传递的参数的存放地址overflow_arg_area。
    本实施例中,va_list结构体包括成员变量参数寄存器的编号gpr、通过栈传递的参数的存放地址overflow_arg_area。固定参数是与参数寄存器一一对应的进行存储,每传递一个固定参数,当前参数寄存器的编号gpr就相应的增加,直到全部的参数寄存器都被使用。通过栈传递的参数的存放地址overflow_arg_area则存储通过栈传递时可变参数所存放的地址信息,在参数查找时,通过该地址查找到相应的可变参数。
    步骤1.3:定义va_start 函数来对va_list结构体进行初始化,通过执行va_start 函数获取第一个可变参数的存放位置;由得到的第一个可变参数的存放位置对va_list结构体进行初始化,使va_list结构体中通过栈传递的参数的存放地址overflow_arg_area初始化为第一个可变参数存放位置前一个存储单元的地址,并将地址值传递给va_arg函数。
    本实施例中,由于固定参数、可变参数在传递存储时采用不同的方式进行处理,因此对于第一个变参数的存放位置存在以下两种情况:
    第一种情况:可变参函数的声明中,固定参数的个数n没有超过参数寄存器的数目N时,则第一个可变参的存放位置就是编译器所指定的栈传递参数的起始位置,而编译器中栈传递参数的起始位置都是固定的,通常是由栈底指针加减一个固定大小的offset得到;
    第二种情况:可变参函数的声明中的固定参数的个数n超过N个时,第一个可变参数的存放位置则位于最后一个固定参数存放位置后面的存储单元。
    本实施例中,执行va_start 函数得到第一个可变参数的存放位置之后,将该存放位置的前一个存储单元的地址值赋给va_list结构体中的成员变量overflow_arg_area。这样无论可变参数是从栈传递参数的起始位置开始存储,还是存储在栈中固定参数所在位置后面的连续空间,第一个可变参数的存放位置都保存在了va_list结构体中。
    本实施例中,当编译器进行编译时,根据函数声明中固定参数的个数对可变参数与固定参数进行不同的处理,步骤(2)的具体步骤为:
    (2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);
    (2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;
    (2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放。
    本实施例中,读取一个参数后,首先判断这个参数是固定参数还是可变参数,判断的方法为:由于可变参函数至少有一个固定参数,则由函数的声明即可以得到固定参数个数n,而编译器会对每一个读取的参数进行计数,如果当前参数的计数小于等于n,则说明该参数为固定参数,当计数大于固定参数个数n之后的参数均为可变参数。
    本实施例中,假设编译器有N个用来传递参数的参数寄存器,对于不超过N个固定参数的一般函数,可以都用参数寄存器来进行传递固定参数,若固定参数超过N个参数,则超过的固定参数部分通过在栈中进行传递??杀洳问纪ü焕唇写?,于是可变参数的存储存在两种情况:
    第一种情况:可变参函数的声明中,固定参数没有超过N个时,则可变参函数从编译器所指定的栈传递参数的起始位置开始依次进行存放;
    第二种情况:声明中的固定参数超过N个时,超出N个的那几个固定参数也通过栈来传递,可变参数从最后一个固定参数的存放位置之后开始依次进行存放。
    如图3所示,本实施例中参数传递方法流程,根据可变参函数原型中参数个数确定固定参数、可变参数的参数传递方式,所有的可变参数全部都通过栈来传递,而根据固定参数个数n确定可变参数所存放的位置。如果为固定参数,则按照一般参数的传递原则在有可用的参数寄存器的条件下,使用参数寄存器{R1, R2, …  RN}来进行传参,第一个固定参数传递时将存储到参数寄存器R1中,然后参数寄存器编号gpr加1,第二个固定参数存储到参数寄存器R2中,以此类推;当没有可用的参数寄存器时,即固定参数的个数n大于参数寄存器的数目N时,多出来的固定参数则通过栈来进行传递。
    当为可变参数时,若没有使用栈传递固定参数,即固定参数的个数n小于等于参数寄存器的数目N,此时参数寄存器仍有剩余或正好使用完,固定参数并不占用栈空间来传递,因此可变参数从编译器所指定的栈传递参数的起始位置ARG1开始存放。栈传递参数的起始位置ARG1为栈底加上一个固定大小的offset,第一个需要通过栈来传递的参数存放在该起始位置,后续的参数相应的依次逐个的存放进起始位置之后的连续栈空间ARG2、ARG3……中。若使用栈传递了固定参数,即固定参数的个数n大于参数寄存器的数量N,固定参数无法全部通过参数寄存器传递,多出来的固定参数就会通过栈来传递,在这种情况下,第N+1个固定参数存储在栈传递参数的起始位置ARG1,第N+2个直到第n个固定参数依次进行存放至连续栈空间ARG2、ARG3……中。此时需要先计算第n个固定参数所存放的地址,然后将第一个可变参存放在第n个固定参数所在位置后面的连续空间中,后续的可变参数再依次向后进行存放。
    本实施例将可变参函数中的将固定参数和可变参数进行分开处理,固定参数按照一般方法处理,优先通过参数寄存器来传参,而将所有的可变参都通过栈来传递。既有效的利用了参数寄存器,避免了硬件资源的浪费,又能分别对固定参数和可变参数进行不同的处理,执行效率高、硬件资源利用率稿、灵活性强。
    本实施例中,步骤(3)的具体实施方法为:通过多次执行va_arg函数来进行遍历参数,同时根据参数类型的特点在正确的位置找到相应的参数。每次执行va_arg函数时,由va_list结构体中通过栈传递的参数的存放地址overflow_arg_area得到上一个参数存储的内存地址,根据上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址,获取当前参数,并更新va_list结构体中通过栈传递的参数的存放地址overflow_arg_area为计算得出的当前参数存储的内存地址,其中当获取第一个可变参数时,通过栈传递的参数的存放地址overflow_arg_area,即上一个参数存储的内存地址,为第一个可变参数存放位置的前一个存储单元的地址。
    由于经过va_start 函数的初始化,va_list结构体中的overflow_arg_area指针已经指向了第一个可变参数存放位置的前一个存储单元位置,通过执行va_arg函数来进行遍历参数,就可以在正确的位置找到相应的参数。执行va_arg函数时,通过获取va_list结构体中通过栈传递的参数的存放地址overflow_arg_area找到参数所在位置,在每执行完一次va_arg函数后,va_list结构体中通过栈传递的参数的存放地址overflow_arg_area都会更新,将当前参数存储的内存地址值赋给va_list结构体,当前参数存储的内存地址也即为下一个参数存放位置的前一个存储单元的地址。这样通过迭代就可以依次获取每一个参数的地址,直到遍历所有的参数。
    步骤(3)的关键问题在于所查找的参数的类型和数据对齐问题,如果一个参数类型的长度、超过一个字时,则该参数之后的参数位置会相应的后移,因此需要在给va_list结构体赋新值的时候要加上正确的位移;而如果当前参数类型的长度小于一个字,则要根据寻址方式来进行相应的对齐处理,以使正确读取到参数值。
    本实施例中,计算出当前参数所存储的内存地址的具体实现方法为:判断当前参数的参数类型的长度是否超过一个字,若为是,将va_list结构体中通过栈传递的参数的存放地址(即上一个参数存储的内存地址)加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻址方式进行对齐处理后得到当前参数存储的内存地址。以下一个参数为单字类型为例,由va_list结构体存储的内存地址值加一个字的大小得到下一个参数要存储的位置;以下一个参数为双字类型为例,则需要加2个字的大小来得到下一个参数要存储的位置。
    本实施例在执行完一次va_arg函数之后,当前va_list结构体指针指向的是当前参数存储的位置,也就是下一个参数所要储存的位置的前一个存储单元,在获得下一个参数的类型和大小之后,可以很方便的通过相加得到下一个参数的地址。传统的处理方法中,在执行完一次va_arg之后指向当前参数位置的后面那个位置,即下一个参数要存储的位置,若下一个参数超过一个字或者不足一个字时,可能会因为对齐方式以及内存存储的方式(大端或者小端模式)的不同需要进行进一步的调整,使得多了一步计算过程。因此采用本实施例进行可变参函数的编译,编译处理更加简单便捷、执行效率更高。
    以上仅是本发明的优选实施方式,本发明的?;し段Р⒉唤鼍窒抻谏鲜鍪凳├?,凡属于本发明思路下的技术方案均属于本发明的?;し段?。应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理前提下的若干改进和润饰,应视为本发明的?;し段?。

    关于本文
    本文标题:一种面向可变参函数的编译实现方法.pdf
    链接地址://www.4mum.com.cn/p-6143450.html
    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    [email protected] 2017-2018 www.4mum.com.cn网站版权所有
    经营许可证编号:粤ICP备17046363号-1 
     


    收起
    展开
  • 四川郎酒股份有限公司获第十二届人民企业社会责任奖年度环保奖 2019-05-13
  • 银保监会新规剑指大企业多头融资和过度融资 2019-05-12
  • 韩国再提4国联合申办世界杯 中国网友无视:我们自己来 2019-05-11
  • 中国人为什么一定要买房? 2019-05-11
  • 十九大精神进校园:风正扬帆当有为 勇做时代弄潮儿 2019-05-10
  • 粽叶飘香幸福邻里——廊坊市举办“我们的节日·端午”主题活动 2019-05-09
  • 太原设禁鸣路段 设备在测试中 2019-05-09
  • 拜耳医药保健有限公司获第十二届人民企业社会责任奖年度企业奖 2019-05-08
  • “港独”没出路!“梁天琦们”该醒醒了 2019-05-07
  • 陈卫平:中国文化内涵包含三方面 文化复兴表现在其中 2019-05-06
  • 人民日报客户端辟谣:“合成军装照”产品请放心使用 2019-05-05
  • 【十九大·理论新视野】为什么要“建设现代化经济体系”?   2019-05-04
  • 聚焦2017年乌鲁木齐市老城区改造提升工程 2019-05-04
  • 【专家谈】上合组织——构建区域命运共同体的有力实践者 2019-05-03
  • 【华商侃车NO.192】 亲!楼市火爆,别忘了买车位啊! 2019-05-03
  • 北京pk10分析软件免费 分分快三稳赚不赔技巧 云南时时购买技巧 福利彩票双色球开奖结果app 福内蒙古时时开奖结果查询 中巨奖的征兆 时时彩每天稳赚一千 排五走势图带连线图 3d都有哪些玩法 pk10技巧 稳赚买法视频 pc蛋蛋计划软件手机版 江西11选5怎么玩 慈善网六肖 跟计划买如何防止连挂 时时彩 后一 稳赚 重庆市时时开奖结果