在C中注册访问(读/写)

时间:2012-06-12 16:27:47

标签: c assembly binary cpu-registers

我对处理器寄存器概念有一些误解。有一个地址寄存器,比方说,0x0345678。该寄存器为32位宽/长(现在无关紧要,哪个字是正确的)。如手册中所述,有某种表/数组:

Position   Value
 0          111111...10b
 1          111111...11b
 2          7A
 .......................
 7          3F7C

我必须访问位置2的值。 我做的第一件事就是:

#define REG 0x0345678

void somereadfunction()
{
   volatile unsigned int *pval = (volatile unsigned int *)REG;
   printf("%x", *(pval | 0x02));
}

正如你已经猜到的那样,这是错误的假设。

另一项努力就是这个:

    for(unsigned int i = 0; i < 3; i++)
    {
        printf("i: %d, res: 0x%08X", i, *((volatile unsigned int *)REG));
    } 

它有效。所以,我的问题是,为什么以及如何?处理器是否仅使用内部的一些魔术算法切换寄存器值,由另一个开发人员编写?我有点困惑。我知道如何使用一些简单的逐位操作来访问寄存器的第三位,但我不明白,如何通过调用寄存器三次,我们将获得正确的值?

事先感谢您的回答。

ADDED:处理器是ARM​​ 7.使用i2c设备。

3 个答案:

答案 0 :(得分:3)

为什么

因为构建硬件设备(连接到ARM处理器)的人可能只声明了一些“属于”设备的地址。然后,他们注意到硬件中的数据比寄存器多,而且更改手册为时已晚,所以他们决定让一些寄存器保存多个值。

如何的?

硬件有一个内部计数器,用于计算处理器的读命令。每次处理器想要从寄存器读取时,硬件都会向其发送另一条数据,由不可见的内部计数器索引,并增加计数器。计数器是3位,因此它计数0,1,...,7,0,1,......等等。

因此,如果要读取索引为2的数据,还必须读取所有其他数据元素(3,4,5,6和7)以重置不可见的计数器。

答案 1 :(得分:2)

内存映射I / O寄存器根据对它们的读写来更改其内容。他们描述它有点奇怪,但通常会将一个值写入控制寄存器,告诉设备访问哪个内部寄存器,然后从另一个位置读取值。

答案 2 :(得分:1)

如果您尝试索引该数组中的第二个位置,

*(pval | 0x02)应该是*(pval + 0x2)

您还可以通过在强制转换前执行REG + 0x8将REG设置为正确的地址,以获得位置2的第三个32位值。

如果此架构使用字节寻址,则意味着每个地址都指向一个字节的数据。因此,您可以从0x345678,0x345678 + 1,0x345678 + 2等读取一个字节的数据。现在,如果您使用的是32位架构,则每次只关注4个字节。所以0x345678是位置0,0x345682是位置1,依此类推。

您还必须考虑内存对齐,因为您无法进行未对齐的访问。它通常在32位架构中以4字节边界对齐。