搜索
bottom↓
回复: 2

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

[复制链接]

出0入0汤圆

发表于 2008-3-11 13:39:51 | 显示全部楼层 |阅读模式
马老师:您好!要麻烦您了.

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

unsigned char Stack[100]; //建立一个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[99]);
}

以上这是网上名为<<建立属于自己的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[100]

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

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

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


1
2



(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[99]);
+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 ----------------------------------------------------------

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 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的具体数值等,产生"原型汇编"代码,然后再编译生成相应的机器码."原形汇编"代码中是没有标号的,全部是真实的地址.你看到的是"原形汇编"代码.
   具体的参考相关编译原理的书籍.

出0入0汤圆

 楼主| 发表于 2008-3-11 21:00:09 | 显示全部楼层
谢谢马老师!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 09:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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