【发布时间】:2018-11-22 09:36:17
【问题描述】:
我正在尝试修改寄存器中的位域。这是我定义了位域的结构:
struct GROUP_tag
{
...
union
{
uint32_t R;
struct
{
uint64_t bitfield1:10;
uint64_t bitfield2:10;
uint64_t bitfield3:3;
uint64_t bitfield4:1;
} __attribute__((packed)) B;
} __attribute__((aligned(4))) myRegister;
...
}
#define GROUP (*(volatile struct GROUP_tag *) 0x400FE000)
当我使用以下行时:
GROUP.myRegister.B.bitfield1 = 0x60;
它不仅会改变 bitfield1,还会改变 bitfield2。该寄存器的值为0x00006060。
代码被编译为以下汇编代码:
ldr r3,[pc,#005C]
add r3,r3,#00000160
ldrb r2,[r3,#00]
mov r2,#00
orr r2,#00000060
strb r2,[r3,#00]
ldrb r2,[r3,#01]
bic r2,r2,#00000003
strb r2,[r3,#01]
如果我尝试直接操作寄存器:
int volatile * reg = (int *) 0x400FE160;
*reg = 0x60
寄存器的值为0x00000060。
我正在使用 GCC 编译器。
为什么我使用结构体和位域时值重复?
编辑
我发现了另一个奇怪的行为:
GROUP.myRegister.R = 0x12345678; // value of register is 0x00021212
*reg = 0x12345678; // value of register is 0x0004567, this is correct (I am programming microcontroller and some bits in register can't be changed)
我更改寄存器值的方法(使用结构和位域)被编译为:
ldr r3,[pc,#00B4]
ldrb r2,[r3,#0160]
mov r2,#00
orr r2,#00000078
strb r2,[r3,#0160]
ldrb r2,[r3,#0160]
mov r2,#00
orr r2,#00000056
strb r2,[r3,#0161]
ldrb r2,[r3,#0162]
mov r2,#00
orr r2,#00000034
strb r2,[r3,#0162]
ldrb r2,[r3,#0163]
mov r2,#00
orr r2,#00000012
strb r2,[r3,#0163]
【问题讨论】:
-
可能不相关(你的代码可以编译,是吗?),但
register是 C 中的关键字,所以你不应该使用它作为名称。跨度> -
我在代码中重命名了一些变量,却忘记了 register 是一个关键字。我编辑了这个问题。我的代码编译了。
-
如果您尝试
GROUP.myRegister.B.bitfield2 = 0x60;会发生什么? bitfield1 也会改变吗? -
它会产生非常奇怪的结果。寄存器的值变成
0x00818181。 -
@Mark 没那么奇怪,
0x8181非常接近0x6060左移两次...
标签: c gcc assembly struct bit-fields