wygood123 发表于 2009-8-24 23:25:18

请教关于堆栈的问题~

问题1:
《第五篇: 完善的协作式的内核 》里面的寄存器变量OSTaskRunningPrio的运算很不对劲!!!
定义方式:register unsigned char OSTaskRunningPrio asm("r3");//正在运行的任务
语    句:OSRdyTbl &= ~(1<<OSTaskRunningPrio);
编译后的汇编结果:
+00000121:   2DE3      MOV   R30,R3         Copy register
+00000122:   E0F0      LDI   R31,0x00         Load immediate
+00000123:   E081      LDI   R24,0x01         Load immediate
+00000124:   E090      LDI   R25,0x00         Load immediate
+00000125:   C002      RJMP    PC+0x0003      Relative jump
+00000126:   0F88      LSL   R24            Logical Shift Left
+00000127:   1F99      ROL   R25            Rotate Left Through Carry
+00000128:   943A      DEC   R3               Decrement
+00000129:   F7E2      BRPL    PC-0x03          Branch if plus
+0000012A:   9580      COM   R24            One's complement
+0000012B:   2228      AND   R2,R24         Logical AND

“r3”寄存器的值竟然被改的面目全非了!!!后续也没有还原!!!
很恶心的地方!是编译器的问题么?花费了偶2天的时间(汇编菜鸟哈)!


问题2:
原帖地址:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=574348&bbs_id=3004
里面的任务调度函数压栈的寄存器是不是有点问题啊?
我使用AVR STUDIO 仿真来看中断函数的压栈,如下:
@0000016C: __vector_9
150:      {
+0000016C:   921F      PUSH    R1               Push register on stack
+0000016D:   920F      PUSH    R0               Push register on stack
+0000016E:   B60F      IN      R0,0x3F          In from I/O location
+0000016F:   920F      PUSH    R0               Push register on stack
+00000170:   2411      CLR   R1               Clear Register
+00000171:   932F      PUSH    R18            Push register on stack
+00000172:   933F      PUSH    R19            Push register on stack
+00000173:   934F      PUSH    R20            Push register on stack
+00000174:   935F      PUSH    R21            Push register on stack
+00000175:   936F      PUSH    R22            Push register on stack
+00000176:   937F      PUSH    R23            Push register on stack
+00000177:   938F      PUSH    R24            Push register on stack
+00000178:   939F      PUSH    R25            Push register on stack
+00000179:   93EF      PUSH    R30            Push register on stack
+0000017A:   93FF      PUSH    R31            Push register on stack
+0000017B:   2D42      MOV   R20,R2         Copy register
+0000017C:   E6E2      LDI   R30,0x62         Load immediate
+0000017D:   E0F0      LDI   R31,0x00         Load immediate
+0000017E:   E020      LDI   R18,0x00         Load immediate

但是原帖里面使用的顺序是:
//根据中断时保存寄存器的次序入栈,模拟一次中断后,入栈的情况
        __asm__ __volatile__("PUSH __zero_reg__");//R1
        __asm__ __volatile__("PUSH __tmp_reg__");//R0
       
        //保存状态寄存器SREG
        __asm__ __volatile__("IN __tmp_reg__,__SREG__");//先将SREG转存到temp_reg,再PUSH
        __asm__ __volatile__("PUSh __tmp_reg__");//保存状态寄存器SREG
       
        __asm__ __volatile__("CLR __zero_reg__");//重新清零R0临时寄存器
       
        __asm__ __volatile__("PUSH r18");//R18
        __asm__ __volatile__("PUSH r19");//R19
        __asm__ __volatile__("PUSH r20");//R20
        __asm__ __volatile__("PUSH r21");//R21
        __asm__ __volatile__("PUSH r22");//R22
        __asm__ __volatile__("PUSH r23");//R23
        __asm__ __volatile__("PUSH r24");//R24
        __asm__ __volatile__("PUSH r25");//R25
        __asm__ __volatile__("PUSH r26");//R26
        __asm__ __volatile__("PUSH r27");//R27
       
        __asm__ __volatile__("PUSH r30");//R30
        __asm__ __volatile__("PUSH r31");//R31
        //R28与R29用于建立在堆栈上的指针
        __asm__ __volatile__("PUSH r28");//R28
        __asm__ __volatile__("PUSH r29");//R29
        //入栈完

这里到底应该采用那种方案来压栈和出栈呢?(偶是菜鸟,高手误骂哈~)

aaa1982 发表于 2009-8-26 08:40:34

没用过AVR,也不了解他的指令集,根据自己的想法说一下,如果错了不好意思。

第一个问题感觉好像没有必要恢复R3寄存器,R3就是用来存放当前运行任务的优先级的,OSRdyTbl &= ~(1<<OSTaskRunningPrio);这

条语句也就是把当前任务从任务就绪列表中删除(这条语句应该是放在任务切换之前,更改一下任务就绪列表,这条语句完了应该就可以根据更改后的任务就绪列表进行任务切换了),这样也可以给低优先级的任务运行的机会。


OSTaskRunningPrio应该是存放在和每个任务相关的结构体里面的,或者直接通过对就绪任务表的操作就可以知道。没有必要对他放在堆

栈里。

个人观点,谢谢

aaa1982

wygood123 发表于 2009-8-26 14:22:29

LS可能没有整体看过《第五篇: 完善的协作式的内核》的代码了。
OSTaskRunningPrio 被当做一个全局变量来使的。只是是以寄存器的形式来使用。可能这样能够优化代码吧。

后来我又认真分析了:
1. 定义方式:register unsigned char OSTaskRunningPrio asm("r3");//正在运行的任务
    “1<<OSTaskRunningPrio” 语句会改变 OSTaskRunningPrio 的值。

2. 定义方式:unsigned char OSTaskRunningPrio ;//正在运行的任务
    “1<<OSTaskRunningPrio” 语句则不会会改变 OSTaskRunningPrio 的值。

也就是说,普通变量是将值中转到寄存器后,用寄存器来运算,移位不会改变原变量值;
      而寄存器变量的移位操作直接改变该寄存器变量的值。

aaa1982 发表于 2009-8-28 11:09:46

LS的能把你说的《第五篇: 完善的协作式的内核》传上来么,怎么goole到的都不是。

wygood123 发表于 2009-8-28 13:51:47

可是我已经贴了地址了~

问题2:
原帖地址:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=574348&bbs_id=3004
页: [1]
查看完整版本: 请教关于堆栈的问题~