在.S中包含头文件以获得一些结构大小

时间:2017-11-16 16:27:12

标签: c gcc assembly struct

我正在尝试编译混合C代码和汇编代码项目,同时尝试在.S文件和某些头文件之间共享信息时,我遇到了问题。

我创建了两个文件,如下所示:

asm.S:

#include "common.h"

.space SOME_STRUCT_SIZE
.word SOME_MAGIC

.globl main
b start

start:
   ; ... code here

COMMON.H:

struct someStruct {
    int data;
};

#define SOME_STRUCT_SIZE sizeof(struct someStruct)
#define SOME_MAGIC 0x12345678

当尝试编译.S文件(arm-linux-gnueabi-gcc -o asm asm.S)时,我收到错误消息,指示汇编程序正在尝试汇编.h文件,并且显然在结构定义上失败。

common.h: Assembler messages:
common.h:2: Error: bad instruction 'int data'

是否可以强制预处理器静态创建两个定义并以汇编代码可以使用的方式插入它们?

谢谢!

2 个答案:

答案 0 :(得分:2)

我实现了@ pm100建议的内容,并且结果很好。

common_bare_gen.c:

#include "common.h"
#include <stdio.h>

void main(void){
    FILE *common_bare_fp;   
    common_bare_fp = fopen("common_bare.h", "w");

    fprintf(common_bare_fp, "#define SOME_STRUCT_SIZE 0x%08x\n", SOME_STRUCT_SIZE);
    fprintf(common_bare_fp, "#define SOME_MAGIC 0x%08x\n", SOME_MAGIC);
    fclose(common_bare_fp);
}

在asm.S我改变了:

#include "common_bare.h"

并在我的Makefile中添加了两个命令来编译和执行common_bare_gen

非常感谢你的帮助!

答案 1 :(得分:1)

这可能看似令人费解但也可能达到同样的目标。您可以创建一个 C 宏,它只为可能需要传播到汇编程序头的字符串和值创建#defines。您可以创建一个使用这些宏来生成定义的函数。然后,您可以使用 GCC -S功能输出程序集,然后使用 GREP 筛选生成的定义,将它们转储到可以包含的包含文件中由程序集(.S)文件使用。

档案gnuasm.h

#define GNUASM_DEFINE_STR(SYMBOL, STR) \
    __asm__  ("#define " SYMBOL " " #STR);

#define GNUASM_DEFINE_VAL(SYMBOL, VALUE) \
    __asm__  ("#define " SYMBOL " %a0" :: "n"(VALUE));

宏中的技巧是使用 asm 指令来发出定义。这将导致它们出现在生成的.s文件中。 GNUASM_DEFINE_STR可以在全局范围内使用,但要GNUASM_DEFINE_VAL工作,您需要将它放在虚函数中。

您的common.h将保持不变:

struct someStruct {
    int data;
};

#define SOME_STRUCT_SIZE sizeof(struct someStruct)
#define SOME_MAGIC 0x12345678

创建一个包含common.h的虚拟 C 文件(它不需要与您的项目链接)和带有虚函数的gnuasm.h宏文件。在这种情况下,我将其称为common-defs.c

#include "gnuasm.h"
#include "common.h"

/* Dummy function used to generate the defines we need */
void common_defines(void)
{
    GNUASM_DEFINE_STR("SOME_STRING", "some string");
    GNUASM_DEFINE_VAL("SOME_STRUCT_SIZE", SOME_STRUCT_SIZE);
    GNUASM_DEFINE_VAL("SOME_MAGIC", SOME_MAGIC);

    return;
}

这个文件是要编译的,并且要像这样生成程序集输出:

gcc common-defs.c -c -S

这会生成一个文件common-defs.s。这是代表 C 代码的汇编代码。然后,我们发出的所有定义都可以使用 GREP 进行解析,然后输出到我们的汇编文件可以包含的包含文件中:

grep "#define" common-defs.s >common.inc

现在,在我们的asm.S文件中,您可以将其添加到顶部:

#include "common.inc"

生成的common.inc文件将显示为:

    #define SOME_STRING "some string"
    #define SOME_STRUCT_SIZE 4
    #define SOME_MAGIC 305419896

当使用struct另一个有用的东西用于汇编时,是成员变量的偏移量。这些可以像这样生成:

GNUASM_DEFINE_VAL("SOME_STRUCT_DATA_OFFSET", offsetof(struct someStruct, data));