这个反汇编如何与给定的C代码相对应?

时间:2015-12-09 21:40:57

标签: c gcc assembly arm

环境:ARM Cortex m4f的GCC 4.7.3(arm-none-eabi-gcc)。裸金属(实际上是MQX RTOS,但这里无关紧要)。 CPU处于Thumb状态。

这是我正在查看的一些代码的反汇编列表:

//.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

这是使用NO优化(-O0)编译的,所以 GCC不应该做任何花哨的事情...... 然而,我没有得到这个代码。 回答后编辑:永远不要假设这一点。我的问题是因为关闭优化而产生了一种错误的安全感。

我已经读过&#34; uxtb r3,r3&#34;是截断32位值的常用方法。你为什么要截断它然后签名扩展?世界上的这个如何等同于C代码中的位掩码操作?

我在这里缺少什么?

编辑:涉及的事物的类型: 因此,FTFE_FSTAT的实际宏扩展归结为

((((FTFE_MemMapPtr)0x40020000u))->FSTAT)

其中struct被定义为

/** 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;

1 个答案:

答案 0 :(得分:6)

两个uxtb指令是编译器是愚蠢的,如果你打开优化它们应该被优化。 sxtb是编译器非常出色,使用了一种在未经优化的代码中不会出现的技巧。

第一个uxtb是由于您从内存中加载了一个字节。编译器将寄存器r3的其他24位归零,以便字节值填满整个寄存器。

第二个uxtb是由于您使用8位值进行AND运算。编译器意识到结果的高24位始终为零,因此它使用uxtb来清除高24位。

uxtb指令都没有任何用处,因为sxtb指令会覆盖r3的高24位。优化器应该实现并在启用优化的情况下进行编译时删除它们。

sxtb指令采用您关心的一位0x80并将其移至寄存器r3的符号位。这样,如果设置了位0x80,则r3变为负数。所以现在编译器可以与0进行比较以确定该位是否已设置。如果该位设置,则bge指令将分支回while循环的顶部。