最近在学ARM的寻址方式,由于对底层并不是特别熟悉,有些问题理解起来有些困难。今天难得弄懂了关于栈的四种操作方法,做个笔记。
-
对于栈的操作一共有四种:空减LDMED、空增LDMEA,满减LDMFD、满增LDMFA。ARM常用的是满减LDMFD。
LDM是对内存数据批量操作
F-full(满) E-空
D-减 A-增
满:sp指向的是一个实际数据,数据入栈时应先修改SP;
空:是SP指向一个空的位置,数据入栈时,先数据,再修改栈针。
减:是指栈向地址小的方向增长
增:是指栈向地址大的方向增长
-
堆栈保存数据和读取数据都是通过唯一的堆栈指针SP来实现的,SP是一个8位专用寄存器(r13),它批示出堆栈顶部在内部RAM块中的位置。
-
**如果是满减栈,在存储数据时,就先修改栈针,再存储数据。例如,将一个字的数据入栈。先sp(r13)-4,然后存入数据。
如果是空减栈,那么,就要先存入数据,再修改栈针sp-4->sp。**
此外还有满增栈与空增栈。
-
LDMFD sp,[r0-r8] ;在这条指令执行后,SP不发生变化,r0-r8共9个寄存器的内容存入指定的内存区。
LDMFD sp!,[r0,r5,r1,r8] ;将寄存器r0、r5、r1、r8中的数据存入
-
需要注意的是,在数据存入时,寄存器序号大的,存在大地址的位置,而寄存器序号小的存在小地址的位置。它们的存储与写在指令中的顺序无关。
-
有没有!的区别是:
没有!,数据存入后,sp指针回到起始位置(sp指针的位置不变)
有!,数据存入后,sp指针指向最后存入数据位置(sp指针位置发生变化)
-
例:设内存地址0x3000是SP(R13)的内容
现在我们将r0 = 0x12 r1=0x34 r5=0x67 r8=0x90
LDMFD sp!,[r0,r5,r1,r8]
解:满减LDMFD:先sp(r13)-4,然后存入数据。![寄存器数据存入满减栈](https://img-blog.csdnimg.cn/20200305170356631.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1RpQW1vXzk5,size_16,color_FFFFFF,t_70)
作业:分别用图、表和数据来描述四种栈,一种普通内存块的操作。
解:设内存地址0x2000是SP(R13)的内容,先将数据0x12345678存入栈(小端序)![数据入栈的四种结果](https://img-blog.csdnimg.cn/20200305165019605.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1RpQW1vXzk5,size_16,color_FFFFFF,t_70)
相关理解:(1)关于大小端:
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。
例:0x12345678
大端序:12 34 56 78
小端序:78 56 34 12
(2)关于栈的数据存储:
栈是先进后出,存储数据都是在sp指针位置向后插入。(解释为什么空增和空减是一样的)
(这是我自己的理解,不知道有没有更专业的说法...)
(3)sp指针位置:
满——sp指向有数据——先加减sp再存入数据
空——sp指向无数据——先存入数据再加减sp
-
**注意:当寄存器入栈时,存储位置只与序号有关,与寄存器在指令中的顺序无关!**
关于栈的四种类型的个人理解
おすすめ
転載: blog.csdn.net/TiAmo_99/article/details/104676968
おすすめ
ランキング