关于MDK对位域的操作选项

1. 问题

调试QuickJS碰到一行语句:

if (vd->scope_level == 0 && vd->func_pool_idx >= 0) 
{
	LOG_OUT("[Info] vd->scope_level %d, vd->func_pool_idx = %d, (vd->func_pool_idx>=0)? %d", vd->scope_level, vd->func_pool_idx, vd->func_pool_idx >= 0);
    
    .....
}

输出的结果:

vd->scope_level 0, vd->func_pool_idx = -1, (vd->func_pool_idx>=0)? 1

明明是 -1 为什么会和0比较会大于0?

2. 分析

经过分析才知道,该成员变量是一个位域变量,占用24bit, 但是是整数有符号定义;

typedef struct JSVarDef {
    JSAtom var_name;
    /* index into fd->scopes of this variable lexical scope */
    int scope_level;
    /* during compilation: 
        - if scope_level = 0: scope in which the variable is defined
        - if scope_level != 0: index into fd->vars of the next
          variable in the same or enclosing lexical scope
       in a bytecode function:
       index into fd->vars of the next
       variable in the same or enclosing lexical scope
    */
    int scope_next;    
    uint8_t is_const : 1;
    uint8_t is_lexical : 1;
    uint8_t is_captured : 1;
    uint8_t var_kind : 4; /* see JSVarKindEnum */
    
    int func_pool_idx : 24; /* only used during compilation : index in
                               the constant pool for hoisted function
                               definition */
} JSVarDef;

经过查汇编知道该位域变量的读取时按照无符号数读取的,其中指令UBFX就是读取的无符号位域指令。

if (vd->scope_level == 0 && vd->func_pool_idx >= 0) {
        0x020cb472:    687b        {h      LDR      r3,[r7,#4]
        0x020cb474:    b9eb        ..      CBNZ     r3,0x20cb4b2 ; 

        0x020cb476:    68f8        .h      LDR      r0,[r7,#0xc]
        0x020cb478:    2101        .!      MOVS     r1,#1
        0x020cb47a:    f3c010d7    ....    UBFX     r0,r0,#7,#24
        0x020cb47e:    e9cd0100    ....    STRD     r0,r1,[sp,#0]
        0x020cb482:    493f        ?I      LDR      r1,[pc,#252] ; [0x20cb580] = 0x8809748
        0x020cb484:    2203        ."      MOVS     r2,#3
        0x020cb486:    3128        (1      ADDS     r1,r1,#0x28
        0x020cb488:    483c        <H      LDR      r0,[pc,#240] ; [0x20cb57c] = 0x6f103002
}

这就导致数据处理流程出现问题!

3. 解决方法

这里的编译环境使用给的arm keil + compiler version5, 经查编译选项 keil中有一个指定位域是否为符号类型的选项;

 为了不影响整个工程的配置,针对QuickJS所在的组单独配置 --signed_bitfields, 如下:

 配置完成之后再次运行程序运行正常,汇编如下:

if (vd->scope_level == 0 && vd->func_pool_idx >= 0) {
        0x020cb47c:    687b        {h      LDR      r3,[r7,#4]
        0x020cb47e:    bb03        ..      CBNZ     r3,0x20cb4c2 ; 
        0x020cb480:    68f8        .h      LDR      r0,[r7,#0xc]
        0x020cb482:    f34010d7    @...    SBFX     r0,r0,#7,#24
        0x020cb486:    2800        .(      CMP      r0,#0
        0x020cb488:    db1b        ..      BLT      0x20cb4c2 ; 

结束!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值