如何在ARM汇编中使用C定义

8

如何在ARM汇编代码中使用LONG_MIN和LONG_MAX等外部定义?

假设我的_arm.h文件如下:

int my_arm(int foo);

假设我有一个my_main.c文件,内容如下:

...
#include <limits.h>   
#include "my_arm.h"
...
int main (int argc, char *argv[])
{
  int foo=0;
...
  printf("My arm assembler function returns (%d)\n", my_arm(foo));
...
}

我的 my_arm.s 文件如下所示:
  .text
  .align 2
  .global my_arm
  .type   my_arm, %function
my_arm:
    ...
    ADDS r1, r1, r2
    BVS overflow
    ...
overflow: 
    LDR r0, LONG_MAX @ this is probably wrong, how to do it correctly?
    BX lr @ return with max value

倒数第二行,我不确定如何正确加载,我模糊地记得在某个地方读到过,我必须在.global中定义LONG_MAX,但现在无法找到一个可行示例的链接。

我正在使用arm-linux-gnueabi-gcc版本4.3.2进行编译。

==================

更新:感谢建议!不幸的是,我仍然在语法上有问题。

首先,我创建了一个小头文件mylimits.h(现在与.S文件在同一目录下)。

#define MY_LONG_MIN 0x80000000

我在 my_arm.S 文件中添加了以下内容:

...
.include "mylimits.h"
...
ldr r7, =MY_LONG_MIN @ when it was working it was ldr r7, =0x80000000
...

这种方法存在两个问题。

首先,最大的问题是:符号MY_LONG_MIN未被识别……所以仍然有些不对劲。

其次,.include语法不允许我包括<limits.h>,我必须在mymylimits.h中添加它,这似乎有点笨拙,但我想,那还好 :)

有什么建议吗?

我可以使用ARM系统开发人员指南设计和优化系统软件[2004]和ARM架构参考手册[2000],我的目标是XScale-IXP42x Family rev 2 (v5l)。


4
不清楚您是否了解ARM,但如果您在使用MIPS,将文件扩展名更改为“.S”会使C对该文件进行预处理。 - Tom
使用#include而不是.include,并且使用.S而不是.s,正如答案中所说。这样你就可以利用gcc的特性,一切都应该像我在x86上的测试一样进行,除了汇编当然是不同的。 - ShinTakezou
5个回答

11
通常,小写的文件扩展名.s意味着汇编程序不应通过c预处理器传递,而大写的扩展名.S意味着应该传递。
尽管如此(GCC端口通常这样做),但取决于您的编译器是否遵循此约定,请检查其文档。
(编辑:请注意,这意味着您可以使用#include指令 - 但请记住,您将包括的大多数文件通常都不是有效的汇编程序(除非它们完全由#define定义组成),因此您可能需要编写自己的头文件)

5年后的编辑:

请注意,armcc v5编译器在Linux下遵循此行为……但在Windows下不遵循。


4
如果使用GCC工具链,则在预处理汇编文件时定义__ASSEMBLER__宏。如果需要,可以使用该宏来帮助.h文件在汇编和C语言之间工作。但是如果可能的话,最好将需要在两个世界中工作的项目分别分隔到不同的头文件中。虽然对于类似于在标准头文件中定义的LONG_MAX这样的内容,你无法进行太多控制... - Michael Burr
是的,它在标准头文件中并没有太多用处!(除了有时用于定义诸如内存映射IO地址之类的架构头文件,这些是为此目的而设计的) - James

2
如果你使用gcc及其汇编器,那么很简单:将文件命名为最终的.S,然后在开头添加#include <limits.h>并在需要常量的地方使用,例如ldr r0, SOMETHING;我在x86上进行了测试,因为这是我所拥有的,但由于它是gcc的功能,因此相同的方法也适用于其他平台。

1
我最终做的是这样的:
在我的 my_main.c 文件中。
#include <limits.h>
...
int my_LONG_MAX=LONG_MAX;

然后在我的_arm.S文件中

ldr r8, =my_LONG_MAX 
ldr r10, [r8] 

看起来很复杂,而且这种方法的可移植性收益也值得怀疑。

必须有一种方法可以直接在汇编中访问LONG_MAX。 如果有这样的方法,我将非常乐意接受它作为完整答案。


如果有人想提出更好的解决方案,我将非常乐意接受该答案。 - Sint
这很丑陋。你为什么要试图在汇编中使用与类型大小相关的定义呢?如果您有一个单一的架构(内在于asm),那么只需直接编写常量即可。它不会改变! - R.. GitHub STOP HELPING ICE
哦,我承认这很糟糕。 :) 这是一个库函数的实现。如果我有办法,我会直接将其写成常量。 - Sint

0

使用 --cpreproc 选项来配置 armasm,并添加

#include "my_arm.h"

放进我的_arm.s文件中。

适用于Keil ARM。


0

我曾经看到,将汇编源代码与 gas 相比,简单地将 gcc 作为前端可以让你在汇编中做类似 C 的事情。当你遇到必须使用 gcc 作为 gas 前端才能使某些东西正常工作的情况时,实际上有点可怕,但这是另一回事。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接