OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11396|回复: 10

UCOSII中OS_CPU_A.asm任务切换汇编代码 SUBS R0, R0, #0x20 为啥R0减去0x20

[复制链接]

18

主题

70

帖子

0

精华

高级会员

Rank: 4

积分
593
金钱
593
注册时间
2015-4-14
在线时间
47 小时
发表于 2018-6-25 23:15:15 | 显示全部楼层 |阅读模式
20金钱
本帖最后由 坏男孩 于 2018-6-26 08:11 编辑

[mw_shl_code=asm,true]PendSV_Handler
    CPSID   I                                                
    MRS     R0, PSP                                            
    CBZ     R0, PendSV_Handler_Nosave                                 
        
      
        TST         R14, #0x10
        IT                 EQ
        VSTMDBEQ R0!, {S16-S31}
        
    SUBS    R0, R0, #0x20         
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCur                              
    LDR     R1, [R1]
    STR     R0, [R1]                                       

                                                         
PendSV_Handler_Nosave
    PUSH    {R14}                                          
    LDR     R0, =OSTaskSwHook                        
    BLX     R0
    POP     {R14}

    LDR     R0, =OSPrioCur                                   
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCur                                    
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2]                                          
    LDM     R0, {R4-R11}                                   
    ADDS    R0, R0, #0x20


        TST         R14, #0x10
        IT                 EQ
        VLDMIAEQ R0!, {S16-S31}
               
        MSR     PSP, R0                                          
    ORR     LR, LR, #0x04                                    
    CPSIE   I
    BX      LR                                            
        NOP
    end  [/mw_shl_code]
其中第11 12行部分
SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11}
这两行百思不得其解,大神给指点下
R0此时指向SP,R0自减0x20,就是SP自减0x20,为啥是这个数值,可否解释一下,还有就是STM指令解释下用法,手册中的都是STMIA,STMDM,啥的,没有纯粹的STM的用法

最佳答案

查看完整内容[请看2#楼]

这个问题最终自己解决了,也许这就是学习的过程吧,自己提问,然后自己解答 SUBS R0, R0, #0x20 这行代码表示R0保存的地址(SP)减去0x20(32),地址为啥呀减去32呢,SP是堆栈栈顶指针,SP减去32就是4*8,这里内存的地址是4个字节间隔访问的,应该是32位的缘故吧,因此也就是SP减去了8个内存的单元,为啥呢?因为马上要手动存储CPU的寄存器R4-R11了,STM R0, {R4-R11} ;保存剩余的R4-R11寄存器 从上面的指令看是先存储R4, ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

18

主题

70

帖子

0

精华

高级会员

Rank: 4

积分
593
金钱
593
注册时间
2015-4-14
在线时间
47 小时
 楼主| 发表于 2018-6-25 23:15:16 | 显示全部楼层
这个问题最终自己解决了,也许这就是学习的过程吧,自己提问,然后自己解答
SUBS R0, R0, #0x20
这行代码表示R0保存的地址(SP)减去0x20(32),地址为啥呀减去32呢,SP是堆栈栈顶指针,SP减去32就是4*8,这里内存的地址是4个字节间隔访问的,应该是32位的缘故吧,因此也就是SP减去了8个内存的单元,为啥呢?因为马上要手动存储CPU的寄存器R4-R11了,STM     R0, {R4-R11}        ;保存剩余的R4-R11寄存器
从上面的指令看是先存储R4,依次到R11,STM指令在CortexM4中是一个连续存储一组寄存器(R4-R11)到一个连续的地址,STM其实还有选项IA,DB
STMIA,IA表示现增加(Increment),再访问(Access)
STMDB,DB表示先减小(Decrement),再访问(Access)
而这里STM默认表示STMIA,也就是说R0(SP)先增加,再访问,也就是先加4,然后存入R4,SP再加4,存入R5,一直到存完R11
这里说明一下,任务切换是通过中断实现的,中断过程会自动保存下面的部分:xPSR ,R15,R14,R12,R3-R0;
  xPSR :    *(stk)    = (INT32U)0x01000000L;             /* xPSR   xPSR T位(第24位)置1,否则第一次执行任务时Fault,                                            */
        //xPSR的第九位为0就是不需要双字节对齐,
        //M4如果开启FPU,就默认是双字节对齐
  R15(PC):  *(--stk)  = (INT32U)task;                    /* Entry Point   PC肯定得指向任务入口,                                     */
  R14(LR): *(--stk)  = (INT32U)OS_TaskReturn;           /* R14 (LR) (init value will cause fault if ever used)*/
  R12:*(--stk)  = (INT32U)0x12121212L;             /* R12                                                */
  R3: *(--stk)  = (INT32U)0x03030303L;             /* R3                                                 */
  R2:  *(--stk)  = (INT32U)0x02020202L;             /* R2                                                 */
  R1: *(--stk)  = (INT32U)0x01010101L;             /* R1                                                 */
  R0: *(--stk)  = (INT32U)p_arg;                   /* R0 : argument   R0用于传递任务函数的参数,因此等于p_arg。                                   */


所以我们需要手动处理的就是R11-R4了,而且是最好按照顺序,R11紧贴着R0,依次为xPSR ,R15,R14,R12,R3,R2,R1,R0,R11,R10,...,R4,(注意,由于堆栈是向下生长的,每次一个入栈,其实内存地址是减小的)
进入中断后因为R0(含)已经入栈了,且R0中存的是栈顶指针,所以R0中的地址减小8*4,就是将SP指定R4该存的地方,执行完STM指令后SP指针就回到R0中了
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2018-6-26 01:07:59 | 显示全部楼层
帮顶
回复

使用道具 举报

18

主题

70

帖子

0

精华

高级会员

Rank: 4

积分
593
金钱
593
注册时间
2015-4-14
在线时间
47 小时
 楼主| 发表于 2018-6-26 08:10:49 | 显示全部楼层
大哥们给解答一下哦
回复

使用道具 举报

18

主题

70

帖子

0

精华

高级会员

Rank: 4

积分
593
金钱
593
注册时间
2015-4-14
在线时间
47 小时
 楼主| 发表于 2018-6-26 08:11:23 | 显示全部楼层

谢谢帮顶,更希望给点解答。。。
回复

使用道具 举报

4

主题

59

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
367
金钱
367
注册时间
2016-8-29
在线时间
128 小时
发表于 2019-12-5 12:04:26 | 显示全部楼层
666666
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2019-5-26
在线时间
8 小时
发表于 2019-12-6 15:53:55 | 显示全部楼层
写的不错,学习了
回复

使用道具 举报

2

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2019-8-17
在线时间
30 小时
发表于 2020-4-2 14:05:36 | 显示全部楼层
stmia 應該是先寫后增加吧,a是after,減32后,從r4開始,到r11,地址自增一次寫進去,剛好R11紧贴着R0,這樣才是正確的,我也找了很多資料
回复

使用道具 举报

66

主题

224

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1349
金钱
1349
注册时间
2018-10-4
在线时间
200 小时
发表于 2020-12-22 22:17:14 | 显示全部楼层
lkj1995 发表于 2020-4-2 14:05
stmia 應該是先寫后增加吧,a是after,減32后,從r4開始,到r11,地址自增一次寫進去,剛好R11紧贴着R0,這樣才是 ...

你是对的
吾虽浪迹天涯 却未迷失本心
欢迎光临我的CSDN博客
回复

使用道具 举报

66

主题

224

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1349
金钱
1349
注册时间
2018-10-4
在线时间
200 小时
发表于 2020-12-22 23:07:07 | 显示全部楼层
本帖最后由 潘长青 于 2020-12-23 15:43 编辑

总所周知,一个指针表示一个8位数据的地址,而通用目的寄存器是32位的,也就是一个通用目的寄存器需要4个指针。
0x20等于32,PSP减去32个指针后,PSP指向空出8个32位宽数据空间的堆栈中的某处,这8个32位宽堆栈空间就是用来存放R4-R11这8个通用目的寄存器的。
STM指令默认为STMIAARMv4中STMLDM指令详解,意思是先往该地址写入数据,之后再增加地址,地址默认每次加4。
因此指令:
SUBS R0,R0,#0x20
STM R0,{R4-R11}
的过程示意如下图所示:
示意.png
注意:在STM指令中,R0后面没有感叹号,所以R0不更新(基地址不写回)。

实际上,在《CM3&CM4权威指南》的第十章,对上下文切换也有提及,相关部分如下:
上下文切换代码.png

上下文切换.png
可以看到,在这里,ARM官方使用的是STMDB R0!,{R4-R11}。
而uCOS-II源码中的这部分,使用了:
SUBS R0,R0,#0x20
STM R0,{R4-R11}
它们与STMDB R0!,{R4-R11}是等价的。
同理,在下面手动出栈部分也是等价的。



吾虽浪迹天涯 却未迷失本心
欢迎光临我的CSDN博客
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2020-12-11
在线时间
1 小时
发表于 2021-12-14 22:10:12 | 显示全部楼层
潘长青 发表于 2020-12-22 23:07
总所周知,一个指针表示一个8位数据的地址,而通用目的寄存器是32位的,也就是一个通用目的寄存器需要4个指 ...

点赞!!!  一个感叹号让我纠结了3天,百思不得其解!!!!  
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 09:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表