【问题标题】:How to get the size of a C global array into an assembly program written for the AVR architecture compiled with GCC?如何将 C 全局数组的大小放入为使用 GCC 编译的 AVR 架构编写的汇编程序中?
【发布时间】:2010-02-01 15:40:24
【问题描述】:

我有一个.c 文件,其中包含以下内容。

uint8_t buffer[32]

我有一个.S 文件,我想在其中执行以下操作。

cpi r29, buffer+sizeof(buffer)

cpi 的第二个参数必须是立即数,而不是位置。但不幸的是sizeof()C 运算符。这两个文件都被编译为单独的目标文件,然后链接在一起。

如果我执行avr-objdump -x file.c,除其他外,我会得到缓冲区的大小。所以它已经在目标文件中可用了。

如何在编译时访问汇编文件中缓冲区的大小?

【问题讨论】:

    标签: c gcc assembly sizeof avr


    【解决方案1】:

    为什么不简单地将数组的长度放入#define ——即直接使用

    #define BUFFER_SIZE 32
    

    #includecS 文件中的#include (.include) 头文件中。

    【讨论】:

    • 这似乎是一个合理的解决方法。但它没有回答我的问题。
    【解决方案2】:

    在链接器运行之前,另一个文件中符号的大小是不可见的;到这个时候,汇编器已经完成了。获得你想要的*的唯一方法是让它成为一个常量,包含在两个文件中。

    * 假设你需要它是一个汇编立即数。

    【讨论】:

    • 这似乎并不完全正确。我可以使用导出为 imidiate 值的符号的地址。
    • 链接器知道如何用它的值替换单个符号 - 但它不具备替换更复杂表达式(如buffer + sizeof(buffer))的智能。
    • 有趣;我会认为因为直接字段通常很小,所以您希望在汇编时显示任何截断警告。
    【解决方案3】:
    uint8_t buffer[32];
    const uint8_t* buf_end;
    buf_end = buffer+sizeof(buffer);
    

    然后

    cpi r29, buf_end
    

    【讨论】:

    • buf_end 给了我可以读取大小的地址,但我需要在编译时将大小作为 imidiate 值。
    • 不,buf_end 为您提供缓冲区结束的地址。它不等于 sizeof()...,它是一个指向刚刚超过缓冲区最后一个元素的内存位置的指针,它等于 buffer+sizeof() 或 &buffer[32] 或 (buffer+32) 如果你需要单独的大小,将其存储在另一个变量中。
    【解决方案4】:

    如果您可以告诉您的 C 编译器可靠地将一些标签(或变量)buffer_end 紧跟在 uint32_t buffer[32]; 之后,那么您的汇编语言代码可以只使用该 buffer_end 引用而不是笨拙地让链接器添加两个值.

    如果您在 .S 文件中定义缓冲区,那么做这样的事情很容易,但在 .c 文件中则不那么容易。

    FWIW,.o 文件可能包含一些大小信息。我为我的一个系统生成了一个带有二进制数据的.o 文件:

    $ avr-objcopy -B avr -I binary -O elf32-avr --readonly-text --rename-section .data=.text,contents,alloc,load,readonly,code foo.bin foo.o
    

    这给了我一个foo.o,它在nm foo.o 之后产生以下内容:

    00000c00 T _binary_foo_bin_end
    00000c00 A _binary_foo_bin_size
    00000000 T _binary_foo_bin_start
    

    _binary_foo_bin_size 的类型如果可以适应您的情况可能会很有用 - 如果您确实需要超过 buffer_end 标签的大小。

    顺便说一句,如果您正在编写具有超过 256 字节 SRAM 的 AVR 芯片,您的代码可能需要正确使用 lo8/hi8 宏来测试所有 16 个地址位。

    【讨论】:

      【解决方案5】:
      uint32_t sizeofbuffer = sizeof(buffer);
      

      然后

      cpi r29, buffer+sizeofbuffer
      

      这应该可行。

      【讨论】:

      • sizeofbuffer 给了我可以读取大小的地址,但我需要在编译时将大小作为 imidiate 值
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多