Chenxg 发表于 2008-3-11 13:39:51

关于建立人工堆栈时遇到的3个问题,请:

马老师:您好!要麻烦您了.

#include <avr/io.h>
void fun1(void)
{
unsigned char i=0;
while(1)
{
   
    PORTB=i++;
    PORTC=0x01<<(i%8);
       
}
}

unsigned char Stack; //建立一个100字节的人工堆栈

void RunFunInNewStack(void (*pfun)(),unsigned char *pStack)
{
*pStack--=(unsigned int)pfun;      //将函数的地址低位压入堆栈,
*pStack--=(unsigned int)pfun>>8;    //将函数的地址高位压入堆栈,
   
   SP=pStack;                              //将堆栈指针指向人工堆栈的栈顶
   __asm__ __volatile__("RET \n\t");    //返回并开中断,开始运行fun1()

}

int main(void)
{

   RunFunInNewStack(fun1,&Stack);
}

以上这是网上名为<<建立属于自己的AVR的RTOS>>中的一段程序代码.
链接:http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=574348&bbs_page_no=1&search_mode=3&search_text=armok&bbs_id=9999


有几个问题向您请教:



(1): 函数的地址是16位,上面将fun1函数的地址低位压入人工堆栈 ,程序语句:*pStack--=(unsigned int)pfun;      //将函数的地址低位压入堆栈,
                  
                     再将fun1函数的地址高位压入人工堆栈 ,程序语句: *pStack--=(unsigned int)pfun>>8;    //将函数的地址高位压入堆栈,

       经过unsigned int 类型转换后,这个数据应该变成了16位的了.但是问题出来了,*pStack是8位的.见前面的定义:unsigned char Stack

这个过程中间难道没有冲突吗?

(2):主函数main()里面, RunFunInNewStack(fun1,&Stack);
                      void RunFunInNewStack(void (*pfun)(),unsigned char *pStack)
                     传递过去的是&Stach;经过以下过程后:

                  {
                      *pStack--=(unsigned int)pfun;      //将函数的地址低位压入堆栈,
                      *pStack--=(unsigned int)pfun>>8;    //将函数的地址高位压入堆栈,
                      SP=pStack;
                  }
单片机内SRAM中数据是不是如下图(1)所示 ,还是如图(2)所示:这个问题和上面的一个问题问得差不多,我只想知道,我的理解是不是正确的. 谢谢.!!


1http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_228175.jpg
2http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_228176.jpg



(3)使用汇编的时候,在程序的开始处要做些准备工作,初始化堆栈,内存区域的使用规划等.但是C语言里从来不考虑这些,对此我感到很不理解.能够简单的说一下这是为什么吗?

            
再说一声谢谢了.!!


下面是上面的程序中在AVR Studio中反汇编的内容.实在是看不懂.比如第一句中的RJMP(相对跳转):
在您的书中73页讲解如下:
RJMP k       -2048=< K =<2047
说明: 相对跳转到(PC-2048)~(PC+2047)字范围内的地址,在汇编过程中,用目的地址的标号替代相对跳转k.怎么反汇编就变成这个样子呢?





+00000008:   C024      RJMP    PC+0x0025      Relative jump
+00000009:   C023      RJMP    PC+0x0024      Relative jump
+0000000A:   C022      RJMP    PC+0x0023      Relative jump
+0000000B:   C021      RJMP    PC+0x0022      Relative jump
+0000000C:   C020      RJMP    PC+0x0021      Relative jump
+0000000D:   C01F      RJMP    PC+0x0020      Relative jump
+0000000E:   C01E      RJMP    PC+0x001F      Relative jump
+0000000F:   C01D      RJMP    PC+0x001E      Relative jump
+00000010:   C01C      RJMP    PC+0x001D      Relative jump
+00000011:   C01B      RJMP    PC+0x001C      Relative jump
+00000012:   C01A      RJMP    PC+0x001B      Relative jump
+00000013:   2411      CLR   R1               Clear Register
+00000014:   BE1F      OUT   0x3F,R1          Out to I/O location
+00000015:   E5CF      LDI   R28,0x5F         Load immediate
+00000016:   E0D4      LDI   R29,0x04         Load immediate
+00000017:   BFDE      OUT   0x3E,R29         Out to I/O location
+00000018:   BFCD      OUT   0x3D,R28         Out to I/O location
+00000019:   E010      LDI   R17,0x00         Load immediate
+0000001A:   E6A0      LDI   R26,0x60         Load immediate
+0000001B:   E0B0      LDI   R27,0x00         Load immediate
+0000001C:   EAE6      LDI   R30,0xA6         Load immediate
+0000001D:   E0F0      LDI   R31,0x00         Load immediate
+0000001E:   C002      RJMP    PC+0x0003      Relative jump
+0000001F:   9005      LPM   R0,Z+            Load program memory and postincrement
+00000020:   920D      ST      X+,R0            Store indirect and postincrement
+00000021:   36A0      CPI   R26,0x60         Compare with immediate
+00000022:   07B1      CPC   R27,R17          Compare with carry
+00000023:   F7D9      BRNE    PC-0x04          Branch if not equal
+00000024:   E010      LDI   R17,0x00         Load immediate
+00000025:   E6A0      LDI   R26,0x60         Load immediate
+00000026:   E0B0      LDI   R27,0x00         Load immediate
+00000027:   C001      RJMP    PC+0x0002      Relative jump
+00000028:   921D      ST      X+,R1            Store indirect and postincrement
+00000029:   3CA4      CPI   R26,0xC4         Compare with immediate
+0000002A:   07B1      CPC   R27,R17          Compare with carry
+0000002B:   F7E1      BRNE    PC-0x03          Branch if not equal
+0000002C:   C01B      RJMP    PC+0x001C      Relative jump
+0000002D:   CFD2      RJMP    PC-0x002D      Relative jump
@0000002E: fun1
---- main.c ---------------------------------------------------------------------------------------
3:      {
+0000002E:   E020      LDI   R18,0x00         Load immediate
+0000002F:   E041      LDI   R20,0x01         Load immediate
+00000030:   E050      LDI   R21,0x00         Load immediate
8:            PORTB=i++;
+00000031:   2F82      MOV   R24,R18          Copy register
+00000032:   5F2F      SUBI    R18,0xFF         Subtract immediate
+00000033:   BB88      OUT   0x18,R24         Out to I/O location
9:            PORTC=0x01<<(i%8);
+00000034:   2F82      MOV   R24,R18          Copy register
+00000035:   7087      ANDI    R24,0x07         Logical AND with immediate
+00000036:   01BA      MOVW    R22,R20          Copy register pair
+00000037:   C002      RJMP    PC+0x0003      Relative jump
+00000038:   0F66      LSL   R22            Logical Shift Left
+00000039:   1F77      ROL   R23            Rotate Left Through Carry
+0000003A:   958A      DEC   R24            Decrement
+0000003B:   F7E2      BRPL    PC-0x03          Branch if plus
+0000003C:   BB65      OUT   0x15,R22         Out to I/O location
+0000003D:   CFF3      RJMP    PC-0x000C      Relative jump
@0000003E: RunFunInNewStack
17:       {
+0000003E:   01FB      MOVW    R30,R22          Copy register pair
18:          *pStack--=(unsigned int)pfun>>8;    //将函数的地址高位压入堆栈,
+0000003F:   2F29      MOV   R18,R25          Copy register
+00000040:   2733      CLR   R19            Clear Register
+00000041:   8320      STD   Z+0,R18          Store indirect with displacement
19:          *pStack--=(unsigned int)pfun;      //将函数的地址低位压入堆栈,
+00000042:   9382      ST      -Z,R24         Store indirect and predecrement
+00000043:   9731      SBIW    R30,0x01         Subtract immediate from word
20:          SP=pStack;                              //将堆栈指针指向人工堆栈的栈顶
+00000044:   BFFE      OUT   0x3E,R31         Out to I/O location
+00000045:   BFED      OUT   0x3D,R30         Out to I/O location
21:          __asm__ __volatile__("RET \n\t");    //返回并开中断,开始运行fun1()
+00000046:   9508      RET                      Subroutine return
+00000047:   9508      RET                      Subroutine return
@00000048: main
26:       {
+00000048:   E5CF      LDI   R28,0x5F         Load immediate
+00000049:   E0D4      LDI   R29,0x04         Load immediate
+0000004A:   BFDE      OUT   0x3E,R29         Out to I/O location
+0000004B:   BFCD      OUT   0x3D,R28         Out to I/O location
28:          RunFunInNewStack(fun1,&Stack);
+0000004C:   EC63      LDI   R22,0xC3         Load immediate
+0000004D:   E070      LDI   R23,0x00         Load immediate
+0000004E:   E28E      LDI   R24,0x2E         Load immediate
+0000004F:   E090      LDI   R25,0x00         Load immediate
+00000050:   DFED      RCALL   PC-0x0012      Relative call subroutine
+00000051:   C000      RJMP    PC+0x0001      Relative jump
+00000052:   CFFF      RJMP    PC-0x0000      Relative jump
+00000053:   E28E      LDI   R24,0x2E         Load immediate
+00000054:   E090      LDI   R25,0x00         Load immediate
+00000055:   DFEB      RCALL   PC-0x0014      Relative call subroutine
+00000056:   C000      RJMP    PC+0x0001      Relative jump
+00000057:   CFFF      RJMP    PC-0x0000      Relative jump
+00000058:   FFFF      ???                      Data or unknown opcode
+00000059:   FFFF      ???                      Data or unknown opcode
+0000005A:   FFFF      ???                      Data or unknown opcode
+0000005B:   FFFF      ???                      Data or unknown opcode
+0000005C:   FFFF      ???                      Data or unknown opcode
+0000005D:   FFFF      ???                      Data or unknown opcode
+0000005E:   FFFF      ???                      Data or unknown opcode
+0000005F:   FFFF      ???                      Data or unknown opcode
+00000060:   FFFF      ???                      Data or unknown opcode
+00000061:   FFFF      ???                      Data or unknown opcode
+00000062:   FFFF      ???                      Data or unknown opcode
+00000063:   FFFF      ???                      Data or unknown opcode
+00000064:   FFFF      ???                      Data or unknown opcode
+00000065:   FFFF      ???                      Data or unknown opcode
+00000066:   FFFF      ???                      Data or unknown opcode
+00000067:   FFFF      ???                      Data or unknown opcode
+00000068:   FFFF      ???                      Data or unknown opcode
+00000069:   FFFF      ???                      Data or unknown opcode
+0000006A:   FFFF      ???                      Data or unknown opcode
---- No Source ----------------------------------------------------------

machao 发表于 2008-3-11 20:22:02

1. 关于 *pStack--=(unsigned int)pfun;的解释
   首先要掌握C语言限制条件:允许数值型变量之间互相赋值,不同类型之间不允许.16位的数据赋给8位的话,高位丢弃.
   在上面的语句中,pfun是指针型变量,不能直接给数值型变量赋值,因此先强行转换成16位的数值型变量(两个重要概念:1.尽管pfun本身是一个数,但它是函数第一句语句的地址,不是数值;2.当代码空间<64K时,指针是16位的,大于64K指针是32位的.M128的代码空间是64K字(128K字节),指针16位够了,如果是M256,就要使用(long)强制转换了,否则就是一个BUG).
   转换成数值后就可以赋值给*pStack了(char也是数值型的,如同BYTE).
   因此,*pStack--=(unsigned int)pfun就是将指向pfun的指针转换成的16位中的低8位赋值到*pStack中,然后pStack减一.

2.根据以上分析,应该是图(1)

3. 在汇编过程中,用目的地址的标号替代相对跳转k.怎么反汇编就变成这个样子呢.
   这里有个"原型汇编"的概念."原型汇编"指转成机器码前一刻,或最贴近机器语言的汇编码,它是不使用任何其它的任何额外的标识符的(寄存器名除外),必须是K的具体数值.
   汇编软件环境为了减轻编程人员的麻烦,允许采用标号,这样对于编程人员就不需要具体计算K的具体数值了.但汇编软件在编译过程中,要先进行"予编译",该过程中包括语法的判断,以及根据标号计算出K的具体数值等,产生"原型汇编"代码,然后再编译生成相应的机器码."原形汇编"代码中是没有标号的,全部是真实的地址.你看到的是"原形汇编"代码.
   具体的参考相关编译原理的书籍.

Chenxg 发表于 2008-3-11 21:00:09

谢谢马老师!
页: [1]
查看完整版本: 关于建立人工堆栈时遇到的3个问题,请: