首页 > 解决方案 > 直接内存映射 GCC 交叉编译

问题描述

我在 Windows 机器上为 ARM CortexA9 使用 gcc 交叉编译器,用于裸机应用程序。对于直接内存映射,我需要访问地址 0x8000_0000。我使用以下 C 代码:

#define PORTBASE_A 0x80000000 
unsigned int volatile * const portA = (unsigned int *) PORTBASE_A;
#define PORTBASE_B 0x70000000
unsigned int volatile * const portB = (unsigned int *) PORTBASE_B;
#define PORTBASE_C 0x080000000
unsigned int volatile * const portC = (unsigned int *) PORTBASE_C;

printf("Portbase_A %p \n",(unsigned int *) portA); // Portbase_A 0xffffffff80000000 
printf("Portbase_B %p \n",(unsigned int *) portB); // Portbase_B 0x70000000 
printf("Portbase_C %p \n",(unsigned int *) portC); // Portbase_C 0xffffffff80000000 
printf("%d\n", sizeof(unsigned int *));     //4    

使用printf("Portbase_A %p \n",(unsigned int *) portA);导致输出 Portbase_A 0xffffffff80000000

问题

尽管我的目标机器是 32 位机器,为什么我得到 64 位地址 (0xffffffff80000000)。我意识到在 0x8000_0000 中的前导位是一个,但是为什么这会导致 32 个前导位的 1 填充?这是由于交叉编译造成的某种人工制品吗?

非常感谢您的回复。

为了完整起见,这是我的分散文件的可视化。 分散文件可视化

标签: cmemoryarmcross-compiling

解决方案


从标准的角度来看,根据C99: 6.3.2.3报价:

5 整数可以转换为任何指针类型。除非前面指定,结果是实现定义的,可能没有正确对齐,可能不指向引用类型的实体,并且可能是一个陷阱表示。56)

由于结果是实现定义的,因此应该由实现来描述。IE。由编译器。关于指针的实现定义行为的 gcc 文档说:

将指针转换为整数或反之亦然的结果(C90 6.3.4、C99 和 C11 6.3.2.3)。

从指针到整数的强制转换 ....

如果指针表示小于整数类型,则从整数到指针的转换丢弃最高有效位,如果指针表示大于整数类型,则根据整数类型的符号进行扩展,否则位不变。

我假设(读作:猜测)在您的平台上:

  • 二进制补码用于表示数字和指针
  • int是 4 个字节
  • 所有指针都有 8 个字节

常量0x800000000x70000000类型都有int。指针有 8 个字节。当您这样做时(unsigned int *)PORTBASE_A,编译器必须将int变量转换为 8 个字节。您的编译器生成执行二进制补码扩展的代码,即。int转换为指针时,对于额外 4 个字节中的所有额外位重复最高有效位。因此,结果值的额外位设置为 1。


推荐阅读