首先是从理论上的东西。。网上转载来的,后边是看AVR代码时得出的一些东西。
硬件仓库:或许也能够称作体系仓库,是坐落片内RAM区。有人说,只需能运用PUSH,POP指令的单片机,都能够说含有硬件仓库。这样的说法我个人觉得不是很全面。经过指令进行压栈和出栈操作仅仅体系仓库中的一种操做。体系仓库还能够被隐含调用。例如,当调用子程序时,体系会主动把回来地址压入仓库,并不需要用户经过指令操作。一般,栈底设在内存的高端,也便是把内存的最高一段空间划作栈区。这些都是向下成长栈。栈指针或许是专用的寄存器,也或许借用一通用寄存器。也有单片机是在数据区里齐截块作栈区,或许是向上成长,也或许是向下成长。
硬件仓库:是经过寄存器SPH,SPL做为索引指针的地址,是调用了CALL,RCALL等函数调用指令后硬件主动填充的仓库!
软件仓库:是编译器为了处理一些参数传递而做的仓库,会由编译器主动发生和处理,能够经过相应的编译选项对其进行修改。
简略一点说,硬件仓库首要做为地址仓库用,而软件仓库首要会被分配成数据仓库!
—摘自《AVR单片机C言语开发入门辅导》-P169—
ICCAVR运用两个仓库:一个用于子程序调用和中止操作的硬件仓库,一个用于传递参数、暂时变量和局部变量的软件仓库。能够运用仓库检测函数检测两个仓库是否溢出。
假如没有硬仓库,你能够选定一个寄存器作仓库指针,经过软件完成仓库操作。移植μC/OS-II也纷歧定要硬仓库。ARM 就很难说它的仓库是软的仍是硬的。32位的ARM指令中没有PUSH、POP指令。ARM习惯上用R13作仓库指针(SP),但用其他寄存器作仓库指针也未常不行。ARM习惯上用LDM/STM(多寄存器加载/存储指令)来操作仓库,压多少,按什么次序都能挑选。应该说ARM是软硬结合的仓库。
C代码(AVR-GCC编译,优化等级-00):
#include <avr/io.h>
int add(int a,int b)
{
int c;
c=a+b;
return c;
}
int main(void)
{
int a=2,b=3,c=0;
c=add(a,b);
//c=sub(a,b);
}
汇编代码:
(省掉一些boot代码)
。。。。。。。
00000054 <__ctors_end>:
54: 11 24 eor r1, r1
56: 1f be out 0x3f, r1 ; 63
58: cf e5 ldi r28, 0x5F ; 95 //此处Y指针和SP都指到了SRAM最高端
5a: d4 e0 ldi r29, 0x04 ; 4
5c: de bf out 0x3e, r29 ; 62
5e: cd bf out 0x3d, r28 ; 61
。。。
0000008e :
#include
int add(int a,int b)
{
8e: cf 93 push r28
90: df 93 push r29 //保存了Y指针,此刻SP现已-2,这儿再减2
92: cd b7 in r28, 0x3d ; 61 //从头定位Y指针跟SP相同。
94: de b7 in r29, 0x3e ; 62
96: 26 97 sbiw r28, 0x06 ; 6 //减掉6,即向下开了6字节的区域,寄存3变量
98: 0f b6 in r0, 0x3f ; 63
9a: f8 94 cli
9c: de bf out 0x3e, r29 ; 62
9e: 0f be out 0x3f, r0 ; 63
a0: cd bf out 0x3d, r28 ; 61
a2: 9a 83 std Y+2, r25 ; 0x02
a4: 89 83 std Y+1, r24 ; 0x01
a6: 7c 83 std Y+4, r23 ; 0x04
a8: 6b 83 std Y+3, r22 ; 0x03
int c;
c=a+b;
aa: 29 81 ldd r18, Y+1 ; 0x01
ac: 3a 81 ldd r19, Y+2 ; 0x02
ae: 8b 81 ldd r24, Y+3 ; 0x03
b0: 9c 81 ldd r25, Y+4 ; 0x04
b2: 82 0f add r24, r18
b4: 93 1f adc r25, r19
b6: 9e 83 std Y+6, r25 ; 0x06
b8: 8d 83 std Y+5, r24 ; 0x05
return c;
ba: 8d 81 ldd r24, Y+5 ; 0x05
bc: 9e 81 ldd r25, Y+6 ; 0x06
be: 26 96 adiw r28, 0x06 ; 6 //加了6个字节空间,Y指针康复到减6之前
c0: 0f b6 in r0, 0x3f ; 63
c2: f8 94 cli
c4: de bf out 0x3e, r29 ; 62
c6: 0f be out 0x3f, r0 ; 63
c8: cd bf out 0x3d, r28 ; 61
ca: df 91 pop r29
cc: cf 91 pop r28
ce: 08 95 ret //弹出仓库中2个字节
000000d0 :
}
int main(void)
{
d0: c9 e5 ldi r28, 0x59 ; 89 //这4句给SP和Y指针从头赋值了,很明显的在SP的
d2: d4 e0 ldi r29, 0x04 ; 4 //上面还有6个字节(SRAM最大到045E),这6个字节
d4: de bf out 0x3e, r29 ; 62 //被寄存了a,b,c三个变量(能够与上面理论对应)
d6: cd bf out 0x3d, r28 ; 61 //经过Y指针来保存了这三个变量到这个区域
int a=2,b=3,c=0;
d8: 82 e0 ldi r24, 0x02 ; 2
da: 90 e0 ldi r25, 0x00 ; 0
dc: 9a 83 std Y+2, r25 ; 0x02
de: 89 83 std Y+1, r24 ; 0x01
e0: 83 e0 ldi r24, 0x03 ; 3
e2: 90 e0 ldi r25, 0x00 ; 0
e4: 9c 83 std Y+4, r25 ; 0x04
e6: 8b 83 std Y+3, r24 ; 0x03
e8: 1e 82 std Y+6, r1 ; 0x06
ea: 1d 82 std Y+5, r1 ; 0x05
c=add(a,b);
ec: 6b 81 ldd r22, Y+3 ; 0x03
ee: 7c 81 ldd r23, Y+4 ; 0x04
f0: 89 81 ldd r24, Y+1 ; 0x01
f2: 9a 81 ldd r25, Y+2 ; 0x02
f4: 0e 94 47 00 call 0x8e //运用call时主动将PC+2的地址压到仓库
f8: 9e 83 std Y+6, r25 ; 0x06
fa: 8d 83 std Y+5, r24 ; 0x05
//c=sub(a,b);
}
fc: 80 e0 ldi r24, 0x00 ; 0
fe: 90 e0 ldi r25, 0x00 ; 0
100: 0c 94 82 00 jmp 0x104 <_exit>
00000104 <_exit>:
104: ff cf rjmp .-2 ; 0x104 <_exit>
r28和r29一同组成SP指针,Y指针能够作为直接寻址,很明显的刚开始的时分Y指针和SP都在045F这儿,后来在高处开了6个字节的空间来寄存暂时变量,所以Y指针成了这个软件仓库的栈顶,在这个过程中都是运用Y和SP的合作来完成变量和数据的改动,以及康复,硬件仓库和软件仓库在这儿现已不怎么区分了。。。不清楚流程能够画个图来加深了解,好了,看了那么久,总算有点感觉了。。
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/zhudong/260917.html