【问题标题】:Direct Memory Mapping GCC Cross-compilation直接内存映射 GCC 交叉编译
【发布时间】:2020-04-07 04:54:55
【问题描述】:

我在 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 填充?这是由于交叉编译造成的某种人工制品吗?

非常感谢您的回复。

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

【问题讨论】:

  • 你能显示你的命令行吗?这很奇怪。 printf("%zu\n", sizeof(unsigned int *)) 说什么?
  • 你究竟是如何编译和链接代码的?
  • printf("%zu\n", sizeof(unsigned int *)); // u printf("%d\n", sizeof(unsigned int *)); //4 4 和你是我提到的电话的输出
  • 我使用 ARM DS-5 SDK 进行编译和链接。
  • 哎呀。 printf("%d %d %d %d\n", sizeof(int), sizeof(long), sizeof(long long), sizeof(uintptr_t)); 和 printf("%ld %lx %lld %llx\n", (long)-1, (long)-1, (long long)-1, (long long)-1); 和 printf("%s\n", _NEWLIB_VERSION ) 的输出是什么? _WANT_IO_C99_FORMATS、_WANT_IO_LONG_LONG 和 _NANO_FORMATTED_IO 等宏是否已定义?

标签: c memory arm cross-compiling


【解决方案1】:

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

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

由于结果是实现定义的,它应该由实现来描述。 IE。由编译器。 gcc documentation about implementation defined behavior of pointers 说:

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

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

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

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

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

常量0x80000000 和0x70000000 的类型为int。指针有 8 个字节。当您执行(unsigned int *)PORTBASE_A 时,编译器必须将int 变量转换为8 个字节。您的编译器会生成执行twos complement sign extension 的代码,即。从int 转换为指针时,对于额外 4 个字节中的所有额外位重复最高有效位。因此,结果值的额外位设置为 1。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-07-10
  • 2012-02-17
  • 1970-01-01
  • 2018-02-09
  • 2019-07-18
  • 2021-12-21
  • 2016-02-05
相关资源
最近更新 更多