【问题标题】:Accessing functions in an ASM file from a C++ program?从 C++ 程序访问 ASM 文件中的函数?
【发布时间】:2010-11-25 13:24:13
【问题描述】:

Over here 我询问了将 ASM 文件翻译成 C 的问题,从回复来看,似乎没有合理的方法可以做到这一点。美好的。因此,其中一个回复建议我只是按原样使用这些功能并完成它。听起来不错。

但是怎么做呢?

天哪,我已经尝试了我能想到的一切!我使用的是 Microchip 品牌的 MCU (PIC18F4480) 和 Microchip 品牌的 IDE (MPLAB IDE),ASM 文件是 Microchip 创作的……所以你会认为我会找到一些使用它们的方法!到目前为止完全没有运气。

我对 ASM(汇编)一无所知。我用 C++ 编写代码,坦率地说,这不会改变。必须有一种方法可以访问 Microchip ASM 文件中的函数,而无需用新语言重写我的所有代码。

如果有人想看看,ASM 文件和应用说明是here

【问题讨论】:

    标签: c++ assembly embedded microchip


    【解决方案1】:

    查看 PIDInt.asm,从 C/C++ 调用函数应该相当简单。 首先,为 VARIABLE DEFINITIONS 中列出的所有内容声明外部变量:

    extern unsigned char error0, error1; /* etc */
    

    然后,为所有具有“Function:”注释的事物声明外部函数,不带参数也不返回结果:

    extern void Proportional(); // extern "C" for C++
    

    要调用其中之一,您需要填充输入变量、调用函数并读取输出变量。

    【讨论】:

    • 对于 C++,他还需要在函数声明中使用 extern "C"
    • 如另一个答案中所述,将 obj 文件链接在一起。
    • 不错的收获。为您详细介绍 Pavel 欢呼。感谢您的帮助。
    • 我还没有真正查看它是否适用(刚刚醒来),但是如果函数确实接受参数并返回结果怎么办? extern 不能这样做吗?
    • 哇 - 这是 Microchip 为此提出的一个非常糟糕的接口(也许 PIC 没有堆栈?我知道 PIC 可能是资源非常低的芯片)。除非芯片真的没有资源,否则我会将 Martin v. Löwis 描述的东西包装在它自己的 C 函数中,并让包装器使用适当的参数,因此只有一小部分代码处理全局变量。
    【解决方案2】:

    我希望您需要以某种方式从汇编代码构建一个对象 (.o) 文件,然后将您的 C++ 文件与该对象文件链接。您可能需要将这些函数声明为 extern "C" 才能从 C++ 调用它们。

    不确定此处的详细信息,C++ 和汇编之间的调用约定可能存在问题,尤其是对于 PIC 等微控制器。

    您是否真的为微控制器使用完整的 C++ 功能集,即对象、虚拟函数、重载等?那……不错,但我认为大多数 PIC 开发仍然是纯 C 语言(当然还有汇编语言)。

    【讨论】:

    • 粗心使用加号。这只是 c
    【解决方案3】:

    通常的方法是使用具有汇编器和 C/C++ 编译器的构建环境和工具。编译器(和汇编器)获取源文件并生成中间目标文件格式。在 Microsoft Windows 上,使用 Microsoft 工具,这些将是 .obj 文件。

    然后使用链接器将 .obj 文件(可能由多种语言(fortran、cobol、c++、c、objective-c、汇编等)生成)链接到单个应用程序二进制文件中。

    目标文件基本上是导出符号的集合,标记小块字节和未解析符号,标记在链接期间需要修补以指向不同目标文件中的某些内容的字节块。

    现在,通常的问题 - 在我体验过的与您不接近的平台上,c++ 编译器没有考虑到任何类型的跨语言二进制兼容性。另一方面,C 编译器是。因此,c++ 编译器制作了高度混乱的符号,将有关参数和返回类型的各种信息合并到符号名称中。这种机制使运算符重载成为可能。

    不管怎样,关键是,

    • 您需要构建 asm 文件。如果您没有汇编程序,那您就不走运了。它可能需要来自与您的 c/c++ 工具集相同的供应商
    • 您需要告诉您的 c++ 程序外部符号的名称。以 c 兼容的方式。这就是头文件的典型用途。

    所以创建一个头文件来保存 pid 代码的函数声明,并在其中放置类似这样的内容:

    extern "C" void PidMain(void);

    现在,在你的 c++ 程序中#include 那个头文件,并确保汇编器生成的目标文件包含在你的环境链接步骤中,你应该是黄金。

    可能涉及某种调用约定。一些环境对于将事物压入堆栈的顺序和/或谁负责堆栈清理有不同的标准。大多数 ms windows 工具集至少支持 __pascal 和 __cdecl 调用约定,因此 declration 看起来像

    extern "C" void __pascal PidMain(void);

    如果您的特定环境中有多个调用约定,我不知道具体知识。所以我不知道这有多大帮助。我猜祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多