环境: GCC 4.7.3 ( ARM -none-eabi-gcc)为ARM皮质m4f.裸金属(实际上是MQX RTOS,但这里不相关)。CPU处于拇指状态。
下面是我正在查看的一些代码的反汇编程序列表:
//.label flash_command
// ...
while(!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
// Compiles to:
12: bf00 nop
14: f04f 0300 mov.w r3, #0
18: f2c4 0302 movt r3, #16386 ; 0x4002
1c: 781b ldrb r3, [r3, #0]
1e: b2db uxtb r3, r3
20: b2db uxtb r3, r3
22: b25b sxtb r3, r3
24: 2b00 cmp r3, #0
26: daf5 bge.n 14 <flash_command+0x14>常量(在扩展宏等之后)包括:
address of FTFE_FSTAT is 0x40020000u
FTFE_FSTAT_CCIF_MASK is 0x80u这是编译时没有优化(-O0),所以GCC不应该做任何花哨.但是我不明白这个密码。的回复编辑:永远不要假设这一点。我的问题是关闭优化时会产生错误的安全感。。
我读过"uxtb r3,r3“是截断32位值的常见方法。你为什么要把它截断两次,然后再签延呢?在世界上,这如何等同于C代码中的位掩蔽操作?
我在这里错过了什么?
编辑:所涉及事项的类型:因此,FTFE_FSTAT的实际宏扩展可以归结为
((((FTFE_MemMapPtr)0x40020000u))->FSTAT)其中,结构被定义为
/** FTFE - Peripheral register structure */
typedef struct FTFE_MemMap {
uint8_t FSTAT; /**< Flash Status Register, offset: 0x0 */
uint8_t FCNFG; /**< Flash Configuration Register, offset: 0x1 */
//... a bunch of other uint_8
} volatile *FTFE_MemMapPtr;发布于 2015-12-09 22:28:29
这两个uxtb指令是编译器愚蠢的,如果打开优化,就应该对它们进行优化。sxtb是一个非常出色的编译器,它使用了您在未优化的代码中不会想到的技巧。
第一个uxtb是因为您从内存中加载了一个字节。编译器正在对寄存器r3的其他24位进行零化,以便字节值填充整个寄存器。
第二个uxtb是因为您是具有8位值的ANDing。编译器意识到结果的上24位总是为零,所以它使用uxtb来清除上24位。
这两个uxtb指令都不起任何作用,因为sxtb指令覆盖了r3的上24位。优化器应该意识到这一点,并在编译时在启用优化时删除它们。
sxtb指令接受您关心的0x80位,并将其移动到寄存器r3的符号位中。这样,如果设置了位0x80,那么r3就变成一个负数。因此,现在编译器可以与0进行比较,以确定是否设置了位。如果没有设置位,则bge指令分支回while循环的顶部。
https://stackoverflow.com/questions/34189516
复制相似问题