查看: 332|回复: 2

看程序学习arm汇编指令

 关闭 [复制链接]

签到天数: 2090 天

连续签到: 2 天

[LV.Master]伴坛终老IIII

发表于 2009-5-10 11:34 | 显示全部楼层 |阅读模式
看程序学习arm汇编指令 今天找了个简单的函数跟一下

void NVODTimerReset()
{
UINT8 i;

for(i = 0;i<MAX_NVOD_TIMER_NUM; i++)
{
if(nvodTimerContent.timer_mode!=TIMER_MODE_OFF)
{
nvodTimerContent.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 <NVODTimerReset+0>: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 <NVODTimerReset+4>:stmdb sp!, {r11, r12, lr, pc}

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

0x00045268 <NVODTimerReset+8>:sub r11, r12, #4; 0x4

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

//为i赋初值0

0x00045270 <NVODTimerReset+16>: mov r3, #0; 0x0

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

//取出i的值         
0x00045278 <NVODTimerReset+24>: ldrbr3, [r11, #-13] 

//i<MAX_NVOD_TIMER_NUM(8)的判断比较           

0x0004527c <NVODTimerReset+28>: cmp r3, #7; 0x7

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

0x00045280 <NVODTimerReset+32>: bhi 0x452e0 <NVODTimerReset+128>  

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

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

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

//把index即i的值读入r2   

0x00045288 <NVODTimerReset+40>: ldrbr2, [r11, #-13] 

//再把r2放入r3           

0x0004528c <NVODTimerReset+44>: mov r3, r2

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

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

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

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

0x0004529c <NVODTimerReset+60>: add r3, r3, r1

//从地址里取出数组元素值
0x000452a0 <NVODTimerReset+64>: ldrbr3, [r3] 

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

0x000452a4 <NVODTimerReset+68>: cmp r3, #0; 0x0 

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

0x000452a8 <NVODTimerReset+72>: beq 0x452d0 <NVODTimerReset+112> 

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

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

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

0x000452b0 <NVODTimerReset+80>: ldrbr2, [r11, #-13]

0x000452b4 <NVODTimerReset+84>: mov r3, r2
0x000452b8 <NVODTimerReset+88>: mov r3, r3, lsl #1
0x000452bc <NVODTimerReset+92>: add r3, r3, r2
0x000452c0 <NVODTimerReset+96>: mov r3, r3, lsl #3

//把要赋值的数组元素的地址保存到r2
0x000452c4 <NVODTimerReset+100>:add r2, r3, r1

//把TIMER_MODE_OFF(0)放入r3

0x000452c8 <NVODTimerReset+104>:mov r3, #0; 0x0  

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

0x000452cc <NVODTimerReset+108>:strbr3, [r2]

//取出保存的循环计数i
0x000452d0 <NVODTimerReset+112>:ldrbr3, [r11, #-13]  

//执行i++       

0x000452d4 <NVODTimerReset+116>:add r3, r3, #1; 0x1   

//保存自加后的i  
0x000452d8 <NVODTimerReset+120>:strbr3, [r11, #-13] 

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

0x000452dc <NVODTimerReset+124>:b 0x45278 <NVODTimerReset+24>  

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




原文地址 http://google.cn
PCOS系统下载站:http://zhuangji.wang

签到天数: 2090 天

连续签到: 2 天

[LV.Master]伴坛终老IIII

 楼主| 发表于 2009-5-10 11:34 | 显示全部楼层

看程序学习arm汇编指令

看程序学习arm汇编指令 今天找了个简单的函数跟一下

void NVODTimerReset()
{
UINT8 i;

for(i = 0;i<MAX_NVOD_TIMER_NUM; i++)
{
if(nvodTimerContent.timer_mode!=TIMER_MODE_OFF)
{
nvodTimerContent.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 <NVODTimerReset+0>: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 <NVODTimerReset+4>:stmdb sp!, {r11, r12, lr, pc}

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

0x00045268 <NVODTimerReset+8>:sub r11, r12, #4; 0x4

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

//为i赋初值0

0x00045270 <NVODTimerReset+16>: mov r3, #0; 0x0

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

//取出i的值         
0x00045278 <NVODTimerReset+24>: ldrbr3, [r11, #-13] 

//i<MAX_NVOD_TIMER_NUM(8)的判断比较           

0x0004527c <NVODTimerReset+28>: cmp r3, #7; 0x7

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

0x00045280 <NVODTimerReset+32>: bhi 0x452e0 <NVODTimerReset+128>  

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

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

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

//把index即i的值读入r2   

0x00045288 <NVODTimerReset+40>: ldrbr2, [r11, #-13] 

//再把r2放入r3           

0x0004528c <NVODTimerReset+44>: mov r3, r2

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

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

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

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

0x0004529c <NVODTimerReset+60>: add r3, r3, r1

//从地址里取出数组元素值
0x000452a0 <NVODTimerReset+64>: ldrbr3, [r3] 

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

0x000452a4 <NVODTimerReset+68>: cmp r3, #0; 0x0 

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

0x000452a8 <NVODTimerReset+72>: beq 0x452d0 <NVODTimerReset+112> 

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

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

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

0x000452b0 <NVODTimerReset+80>: ldrbr2, [r11, #-13]

0x000452b4 <NVODTimerReset+84>: mov r3, r2
0x000452b8 <NVODTimerReset+88>: mov r3, r3, lsl #1
0x000452bc <NVODTimerReset+92>: add r3, r3, r2
0x000452c0 <NVODTimerReset+96>: mov r3, r3, lsl #3

//把要赋值的数组元素的地址保存到r2
0x000452c4 <NVODTimerReset+100>:add r2, r3, r1

//把TIMER_MODE_OFF(0)放入r3

0x000452c8 <NVODTimerReset+104>:mov r3, #0; 0x0  

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

0x000452cc <NVODTimerReset+108>:strbr3, [r2]

//取出保存的循环计数i
0x000452d0 <NVODTimerReset+112>:ldrbr3, [r11, #-13]  

//执行i++       

0x000452d4 <NVODTimerReset+116>:add r3, r3, #1; 0x1   

//保存自加后的i  
0x000452d8 <NVODTimerReset+120>:strbr3, [r11, #-13] 

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

0x000452dc <NVODTimerReset+124>:b 0x45278 <NVODTimerReset+24>  

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




原文地址 http://google.cn
PCOS系统下载站:http://zhuangji.wang

签到天数: 2090 天

连续签到: 2 天

[LV.Master]伴坛终老IIII

 楼主| 发表于 2009-5-10 11:34 | 显示全部楼层

看程序学习arm汇编指令

看程序学习arm汇编指令 今天找了个简单的函数跟一下

void NVODTimerReset()
{
UINT8 i;

for(i = 0;i<MAX_NVOD_TIMER_NUM; i++)
{
if(nvodTimerContent.timer_mode!=TIMER_MODE_OFF)
{
nvodTimerContent.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 <NVODTimerReset+0>: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 <NVODTimerReset+4>:stmdb sp!, {r11, r12, lr, pc}

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

0x00045268 <NVODTimerReset+8>:sub r11, r12, #4; 0x4

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

//为i赋初值0

0x00045270 <NVODTimerReset+16>: mov r3, #0; 0x0

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

//取出i的值         
0x00045278 <NVODTimerReset+24>: ldrbr3, [r11, #-13] 

//i<MAX_NVOD_TIMER_NUM(8)的判断比较           

0x0004527c <NVODTimerReset+28>: cmp r3, #7; 0x7

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

0x00045280 <NVODTimerReset+32>: bhi 0x452e0 <NVODTimerReset+128>  

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

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

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

//把index即i的值读入r2   

0x00045288 <NVODTimerReset+40>: ldrbr2, [r11, #-13] 

//再把r2放入r3           

0x0004528c <NVODTimerReset+44>: mov r3, r2

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

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

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

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

0x0004529c <NVODTimerReset+60>: add r3, r3, r1

//从地址里取出数组元素值
0x000452a0 <NVODTimerReset+64>: ldrbr3, [r3] 

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

0x000452a4 <NVODTimerReset+68>: cmp r3, #0; 0x0 

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

0x000452a8 <NVODTimerReset+72>: beq 0x452d0 <NVODTimerReset+112> 

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

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

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

0x000452b0 <NVODTimerReset+80>: ldrbr2, [r11, #-13]

0x000452b4 <NVODTimerReset+84>: mov r3, r2
0x000452b8 <NVODTimerReset+88>: mov r3, r3, lsl #1
0x000452bc <NVODTimerReset+92>: add r3, r3, r2
0x000452c0 <NVODTimerReset+96>: mov r3, r3, lsl #3

//把要赋值的数组元素的地址保存到r2
0x000452c4 <NVODTimerReset+100>:add r2, r3, r1

//把TIMER_MODE_OFF(0)放入r3

0x000452c8 <NVODTimerReset+104>:mov r3, #0; 0x0  

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

0x000452cc <NVODTimerReset+108>:strbr3, [r2]

//取出保存的循环计数i
0x000452d0 <NVODTimerReset+112>:ldrbr3, [r11, #-13]  

//执行i++       

0x000452d4 <NVODTimerReset+116>:add r3, r3, #1; 0x1   

//保存自加后的i  
0x000452d8 <NVODTimerReset+120>:strbr3, [r11, #-13] 

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

0x000452dc <NVODTimerReset+124>:b 0x45278 <NVODTimerReset+24>  

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




原文地址 http://google.cn
PCOS系统下载站:http://zhuangji.wang

本版积分规则