This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TM4C1294NCPDT:是否有方法更改某些函数中的调用惯例?

Guru**** 2589265 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/672771/compiler-tm4c1294ncpdt-is-there-a-way-of-changing-the-calling-conventions-in-some-functions

器件型号:TM4C1294NCPDT

工具/软件:TI C/C++编译器

我正在编写操作系统、但我一直在尝试为新任务准备初始堆栈帧。 ARM 的调用惯例规定、某些参数在寄存器 r0-R3上传递(这取决于每个参数的大小)、其他参数在栈上传递。 此外、如果参数是在不同的寄存器上传递的浮点数字、那么这一问题就会变得更加困难。这种惯例使得 create_task 函数难以为新任务准备初始堆栈帧。 是否有办法改变这种情况?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    无法更改特定函数的调用约定。 TI 编译器确实支持"naked"属性、这会抑制序言和结语、但这并不是您真正需要的。

    将初始帧视为新进程的启动代码。 该帧实际上不是通过调用函数创建的、您不会像普通函数那样从该帧返回。 因此,这一框架无需期望其论点与《公约》所期望的相同。

    如果您尝试在 C 代码中编写此函数、是否确实需要任意参数? 如果限制参数数量、则应能够编译函数并查看编译器期望参数的位置、并根据该值对创建的帧建模。 如果您将其限制为零个参数、则应该非常容易。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的帮助、考古学家。 我认为您完全理解我的问题。 但是、让我做一些更多的解释来准确地说明我要做的事情。

    我想定义一个以更简单的方式创建任务(甚至是具有不同数量和类型参数的任务)的函数。 我认为大多数 RTOS 将参数传递给任务的方式非常奇怪、很难使用。 我知道他们都是出于某种原因采用这一功能 的、但我仍然想尝试另一种方法。

    下面是我要做的事情的草稿:

    void task1();
    void task2(int I);
    void task3(char c、int i、const char* s);
    
    create_task (void* task、size_t params_size、...);
    
    int main()
    {
    create_task (task1、0);
    create_task (task2、sizeof (int)、13);
    create_task (task3、sizeof (char)+ sizeof (int)+ sizeof (char*)、'A'、13、"string");
    
    返回0;
    } 

    您看到了吗? 如果我可以更改任务函数的调用惯例、我将能够准确地定义任务函数、与任何其他 C 函数的操作方式完全相同。 此外、我可以将任何数量和类型的参数传递给该函数。 我只需要通知 create_task 将被压入栈的参数的总大小。 这样、将参数从 create_task 的栈框复制到新创建的任务的栈框会很容易。 我假设是一个调用惯例、在这里我会传递栈上的每个参数。

    但您已经说过、我无法更改调用惯例。 所以、我只是提出我的想法、尽管现在我知道不可能实现它。

    如果出现以下情况、将会很有趣:

    void Task1 (int i、char c)__attribute__((args_in_stack)); 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嗯、请注意、当你使用可变参数("...)时、所有参数都通过"... 在堆栈上传递、以及最后一个"已知"参数。 如果您有某种方法可以告诉"create_task"参数的数量和每个参数的类型(例如、考虑 printf 格式字符串)、则理论上、您可以在"create_task"中编写代码、以便从堆栈中提取这些参数。 不过,我怀疑这最终会比它更难实施。

    您可以将参数添加到 va_list 中、并缩小 API 范围以传递 va_list、而不是各种可能的选项组合:

    void create_task (void *任务,size_t n_args,...)

    va_list args;
    va_start (args、n_args);
    V_helper (task、n_args、args);
    VA_END (args);


    void magic_helper_1 (void *任务、size_t n_args、va_list args)

    /*操作系统魔法来构建此虚假函数
    创建不带的初始帧
    担心可变参数*/
    magic_os_stuff;


    void magic_helper_2 (void)

    /*操作系统魔术来构建此虚假功能;
    最后、调用 launchpad */
    LaunchPad (n_args、args);


    void launchpad (size_t n_args、va_list args)

    /*此函数用 C */编写
    = va_arg (args、int);
    /*现在执行真正的任务*/
    task();
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    考古学家

    您说 TI 编译器确实支持"naked"属性。 我已经过测试、编译器确实使用该功能编译了程序、但ARM 优化 C/C++编译器 v18.1.0.LTS 用户指南》的第5.16.2节"函数属性"中未列出裸机。 我还在该文件中进行了字搜索、但在手册中没有发现任何裸字出现。 手动是否已过时或未正式支持 naked 属性?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您提请我们注意此问题。  我在 SDOWP 系统中提交了 CodeGen-4631、以更新 ARM 编译器手册以记录属性 naked。  欢迎您在我的签名中使用下面的 SDOWP 链接进行访问。

    谢谢、此致、

    乔治