Chinaunix首页 | 论坛 | 博客
  • 博客访问: 283996
  • 博文数量: 150
  • 博客积分: 2396
  • 博客等级: 大尉
  • 技术积分: 1536
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-19 09:55
文章分类

全部博文(150)

文章存档

2021年(1)

2015年(9)

2014年(7)

2013年(50)

2012年(33)

2011年(1)

2010年(13)

2009年(36)

我的朋友

分类: LINUX

2009-05-05 20:21:29

今天找了个简单的函数跟一下

void NVODTimerReset()
{
    UINT8 i;

    for(i = 0;i    {
        if(nvodTimerContent[i].timer_mode!=TIMER_MODE_OFF)
        {
            nvodTimerContent[i].timer_mode = TIMER_MODE_OFF;
        }
    }
}
数据说明:
#define MAX_NVOD_TIMER_NUM 8
#define TIMER_MODE_OFF 0
TIMER_SET_CONTENT nvodTimerContent[MAX_NVOD_TIMER_NUM];

typedef struct{
 UINT8 timer_mode;
 UINT8 timer_service;
 UINT16 wakeup_year;
 UINT8 wakeup_month;
 UINT8 wakeup_day;
 UINT32 wakeup_time;
 UINT16 wakeup_duration_time;
 UINT8 wakeup_chan_mode;
 UINT32 wakeup_channel;
 UINT8 wakeup_message;
 UINT8 wakeup_state;
} TIMER_SET_CONTENT;

 

对应函数NVODTimerReset()的汇编:

//先把sp的值保存到r12

0x00045260 mov     r12, sp  

//把 pc+8,lr,r12,r11中的值依次入栈,db表示在传送前地址减1(这样就指向了栈顶的第一个空元素),pc+8->sp-1,lr->sp-5,r12->sp-9,r11->sp-13.并将sp中的值更新为新的栈顶sp-17(放完了r11的四个字节)指向存放r11的最后一个字节单元         

0x00045264 stmdb   sp!, {r11, r12, lr, pc}  

//把r12中的值减4送入r11,相当于r11中的地址值就是上一条命令存入内容的最后一个字节地址.             

0x00045268 sub     r11, r12, #4    ; 0x4    

//把sp中的地址往栈顶上移四个字节出来             
0x0004526c : sub     sp, sp, #4      ; 0x4  

//为i赋初值0               

0x00045270 : mov     r3, #0  ; 0x0

//先保存i的值。r11减13后刚好是存放完stmdb指令中r11的栈顶第一个空地址值 
0x00045274 : strb    r3, [r11, #-13]  

//取出i的值          
0x00045278 : ldrb    r3, [r11, #-13] 

//i

0x0004527c : cmp     r3, #7; 0x7   

//上面判断结果是大于,则跳出循环                      

0x00045280 : bhi     0x452e0   

//继续循环,首先保存出循环跳转需要的指令地址到r1   

0x00045284 : ldr     r1, [pc, #88]   ; 0x452e4 <$d> 

//取数组元素是这样一个原理:根据数组下标index来计算数组元素到数组起始地址的偏移,在把该偏移加上数组起始地址就得到了需要取出元素的地址。此处,结构体的大小是24个字节,因此在计算偏移值的时候是把index的值乘上24的,指令中把24拆分成移位运算。先看取值的第一条指令

//把index即i的值读入r2   

0x00045288 : ldrb    r2, [r11, #-13] 

//再把r2放入r3           

0x0004528c : mov     r3, r2

//把r3左移移位,即把i值乘上2
0x00045290 : mov     r3, r3, lsl #1

//将乘上2后和乘2前的i相加,即是把i乘上3
0x00045294 : add     r3, r3, r2

//在上面的基础上把i左移3位,即又乘上了8,前前后后就乘上了24,刚好等于结构体(四字节对齐)的大小
0x00045298 : mov     r3, r3, lsl #3

//最后把数组起始地址与偏移值相加,得到需要取出元素地址值

0x0004529c : add     r3, r3, r1  

//从地址里取出数组元素值                           
0x000452a0 : ldrb    r3, [r3] 

//把取出的值与TIMER_MODE_OFF(0)比较               

0x000452a4 : cmp     r3, #0  ; 0x0 

//上面比较结果相等,则跳转            

0x000452a8 : beq     0x452d0  

//上面比较结果不等,保存需要跳转用的指令地址到r1     

0x000452ac : ldr     r1, [pc, #48]   ; 0x452e4 <$d>

//这里就和上面取值是一个道理了     

0x000452b0 : ldrb    r2, [r11, #-13]                        

0x000452b4 : mov     r3, r2
0x000452b8 : mov     r3, r3, lsl #1
0x000452bc : add     r3, r3, r2
0x000452c0 : mov     r3, r3, lsl #3

//把要赋值的数组元素的地址保存到r2
0x000452c4        add     r2, r3, r1   

//把TIMER_MODE_OFF(0)放入r3                  

0x000452c8        mov     r3, #0  ; 0x0  

//把r3的值保存到r2中地址对应的存储单元,即为数组成员赋值       

0x000452cc        strb    r3, [r2]   

//取出保存的循环计数i                    
0x000452d0        ldrb    r3, [r11, #-13]  

//执行i++       

0x000452d4        add     r3, r3, #1      ; 0x1   

//保存自加后的i  
0x000452d8        strb    r3, [r11, #-13] 

//无条件跳转到0x45278,重新进行i的判断后循环       

0x000452dc             0x45278   

0x000452e0        ldmib   sp, {r11, sp, pc}
0x000452e4 <$d+0>:      addeqs  r6, r12, r12, lsl #25

阅读(916) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~