关于建立人工堆栈时遇到的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 ---------------------------------------------------------- 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的具体数值等,产生"原型汇编"代码,然后再编译生成相应的机器码."原形汇编"代码中是没有标号的,全部是真实的地址.你看到的是"原形汇编"代码.
具体的参考相关编译原理的书籍. 谢谢马老师!
页:
[1]