2015-02-11 62 views
1

我目前正在编写一个基本的操作系统作为一个学习项目。为此我使用了gcc 4.9.2交叉编译器。 当试图使用存储器映射的I/O I偶然发现C指针(或可能存储器映射I/O),我无法理解的行为。 当通过下面的代码直接访问I/O存储器,I得到预期的结果,这是一个“AB”在黑色背景上的浅灰色字体的左上角。奇怪的行为映射I/O

*((uint16_t *)0xB8000) = 0x0741; 
*((uint16_t *)0xB8002) = 0x0742; 

但是试图通过使用偏移添加2基地址来操纵存储器当结果没有作为在第二但在第三位置预期的“A”。

*((uint16_t *)0xB8000 + 2) = 0x0741; 

添加1而不是2打印第二个位置的字母,但我不明白为什么。由于每个字母(在MMIO中)由2个字节的数据组成,因此我认为我需要将我写入的内存地址增加2,以便为下一个字符。 (正如我在第一次做直接写入0xB8002) 为了尝试和理解这种行为,我做了一个单独的C程序的一些测试,但无法复制这种行为: (注:此代码被编译使用普通的gcc 4.8 0.2)

#include <stdint.h> 
#include <stdio.h> 

void main(void) { 
     printf("0xB8000 + 1 = %x\n", 0xB8000 + 1); 
     printf("&(*(uint16_t *)(0xB8000 + 1)) = %x\n", (uint32_t)&(*(uint16_t *)(0xB8000 + 1))); 
} 

这个程序产生的输出如下:

0xB8000 + 1 = b8001 
&(*(uint16_t *)(0xB8000 + 1)) = b8001 

我认为我缺少某种C指针的行为,这将导致保理在由写入的数据的大小一份声明。这是这种情况还是我有忽略的另一个原因?

问候,Kenshooak

+2

你可能会受益于重新读指针运算基础(总是由基本型缩放)。或者,也许运算符优先级(强制转换优先级高于“+”)。 – Deduplicator 2015-02-11 18:23:34

+0

此外,您可能需要使用'volatile'这里,以确保编译器不自作聪明,优化作业了。 – 2015-02-11 18:49:49

回答

4

如果添加到<type>指针的地址是由sizeof(<type>) * n字节递增的整数n。 所以在你的第一个例子,你有

*((uint16_t *)0xB8000 + 2) = 0x0741; 

等什么这里发生的情况是:0xB8000被转换为unit16_t *,然后该指针递增2,这意味着2 * sizeof(uint16_t) = 4个字节

在第二个例子中,你有

*(uint16_t *)(0xB8000 + 1) 

注意不同的包围:在这里你首先加1到0xB8000--一个简单的整数运算 - 然后转换结果。

+0

非常感谢,我完全错过了不同的包围可能会对结果产生影响! – kenshooak 2015-02-11 18:40:13