对XSCALE 堆栈结构的探讨
实验环境:
IXP 2400 (XSCALE ),小字节模式
实验代码:
int william_test_muti(int var)
{
0x1c72c0 _william_test_muti: MOV r12,r13
0x1c72c4 +0x004: STMDB r13!,{r11,r12,r14,pc}
0x1c72c8 +0x008: SUB r11,r12,#4
0x1c72cc +0x00c: SUB r13,r13,#0xc
0x1c72d0 +0x010: STR r0,[r11,#-0x10]
int d = 0,z = 10;
0x1c72d4 +0x014: MOV r3,#0
0x1c72d8 +0x018: STR r3,[r11,#-0x14]
0x1c72dc +0x01c: MOV r3,#0xa
0x1c72e0 +0x020: STR r3,[r11,#-0x18]
d = var*z;
0x1c72e4 +0x024: LDR r3,[r11,#-0x10]
0x1c72e8 +0x028: LDR r2,[r11,#-0x18]
0x1c72ec +0x02c: MUL r3,r2,r3
0x1c72f0 +0x030: STR r3,[r11,#-0x14]
taskSuspend(0);
0x1c72f4 +0x034: MOV r0,#0
0x1c72f8 +0x038: BL _taskSuspend
return d;
0x1c72fc +0x03c: LDR r3,[r11,#-0x14]
0x1c7300 +0x040: MOV r0,r3
0x1c7304 +0x044: B _william_test_muti + 0x48
}
0x1c7308 +0x048: LDMDB r11,{r11,r13,pc}
int william_test_add(int a,int b)
{
0x1c730c _william_test_add: MOV r12,r13
0x1c7310 +0x004: STMDB r13!,{r11,r12,r14,pc}
0x1c7314 +0x008: SUB r11,r12,#4
0x1c7318 +0x00c: SUB r13,r13,#0x14
0x1c731c +0x010: STR r0,[r11,#-0x10]
0x1c7320 +0x014: STR r1,[r11,#-0x14]
int c = 0;
0x1c7324 +0x018: MOV r3,#0
0x1c7328 +0x01c: STR r3,[r11,#-0x18]
int d = 0x99;
0x1c732c +0x020: MOV r3,#0x99
0x1c7330 +0x024: STR r3,[r11,#-0x1c]
int result = 0;
0x1c7334 +0x028: MOV r3,#0
0x1c7338 +0x02c: STR r3,[r11,#-0x20]
c = a+b+d ;
0x1c733c +0x030: LDR r3,[r11,#-0x10]
0x1c7340 +0x034: LDR r2,[r11,#-0x14]
0x1c7344 +0x038: ADD r3,r3,r2
0x1c7348 +0x03c: LDR r2,[r11,#-0x1c]
0x1c734c +0x040: ADD r3,r3,r2
0x1c7350 +0x044: STR r3,[r11,#-0x18]
result = william_test_muti(c);
0x1c7354 +0x048: LDR r0,[r11,#-0x18]
0x1c7358 +0x04c: BL _william_test_muti
0x1c735c +0x050: MOV r3,r0
0x1c7360 +0x054: STR r3,[r11,#-0x20]
return c;
0x1c7364 +0x058: LDR r3,[r11,#-0x18]
0x1c7368 +0x05c: MOV r0,r3
0x1c736c +0x060: B _william_test_add + 0x64
}
0x1c7370 +0x064: LDMDB r11,{r11,r13,pc}
实验结果:
-> william_test_add 1,5
-> ti t1
NAME ENTRY TID PRI STATUS PC SP ERRNO DELAY
---------- ------------ -------- --- ---------- -------- -------- ------- -----
t1 2d8488 2f31298 4 SUSPEND 2a696c 2f311cc 0 0
stack: base 0x2f31298 end 0x2f2c298 size 20476 high 252 margin 20224
options: 0x1d
VX_SUPERVISOR_MODE VX_DEALLOC_STACK VX_FP_TASK VX_STDIO
r0 = 0 r1 = 0 r2 = 0 r3 = 0
r4 = 2f31298 r5 = 2f31298 r6 = 0 r7 = 0
r8 = 2f31448 r9 = 0 r10 = 0 r11/fp = 2f31200
r12/ip = 3e1508 r13/sp = 2f311cc r14/lr = 0 pc = 2a696c
cpsr = 13
value = 0 = 0x0
->
->
-> d 0x2f311cc-0x20
02f311a0: 3fb7 0000 * ?..*
02f311b0: eeee eeee 64c0 0314 1298 02f3 1200 02f3 *.....d..........*
02f311c0: 11cc 02f3 64c0 0314 e86c 0030 eeee eeee *.....d..l.0.....*
02f311d0: eeee eeee eeee eeee eeee eeee 0000 0000 *................*
02f311e0: 0000 0000 72fc 001c 000a 0000 0636 0000 *.....r......6...*
02f311f0: 009f 0000 1224 02f3 1204 02f3 735c 001c *....$.......\s..*
02f31200: 72cc 001c 0000 0000 0099 0000 009f 0000 *.r..............*
02f31210: 0005 0000 0001 0000 0000 0000 1228 02f3 *............(...*
02f31220: 8514 002d 7318 001c 0000 0000 0000 0000 *..-..s..........*
02f31230: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31240: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31250: 0000 0000 e92c 0030 0000 0000 0000 0000 *....,.0.........*
02f31260: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31270: 1448 02f3 0005 0000 0000 0000 0000 0000 *H...............*
02f31280: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31290: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f312a0: 0004 0000 0000 0000 0000 0000 *................*
value = 21 = 0x15
结果分析:
-> d 0x2f311cc-0x20
02f311a0: 3fb7 0000 * ?..*
02f311b0: eeee eeee 64c0 0314 1298 02f3 1200 02f3 *.....d..........*
02f311c0: 11cc 02f3 64c0 0314 e86c 0030 eeee eeee *.....d..l.0.....*
02f311d0: eeee eeee eeee eeee eeee eeee 0000 0000 *................*
<传递参数>
02f311e0: 0000 0000 72fc 001c 000a 0000 0636 0000 *.....r......6...*
<r0内容> (执行语句)z d
02f311f0: 009f 0000 1224 02f3 1204 02f3 735c 001c *....$.......\s..*
<传递参数>R11 R12 <返回地址>
02f31200: 72cc 001c 0000 0000 0099 0000 009f 0000 *.r..............*
<当前PC> result d c
02f31210: 0005 0000 0001 0000 0000 0000 1228 02f3 *............(...*
参数b 参数a
02f31220: 8514 002d 7318 001c 0000 0000 0000 0000 *..-..s..........*
PC
02f31230: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31240: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31250: 0000 0000 e92c 0030 0000 0000 0000 0000 *....,.0.........*
02f31260: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31270: 1448 02f3 0005 0000 0000 0000 0000 0000 *H...............*
02f31280: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f31290: 0000 0000 0000 0000 0000 0000 0000 0000 *................*
02f312a0: 0004 0000 0000 0000 0000 0000 *................*
value = 21 = 0x15
XSCALE 堆栈变化原则:
1:堆栈结构
内存低地址 --------------------------------------------------------- <--------栈顶(r13)
| 函数局部变量(先定先入栈) |
---------------------------------------------------------
| 当前传入参数(先有先进入栈) |
---------------------------------------------------------
| 上一个函数r11 |
---------------------------------------------------------
| r12(记录单前PC之下的第一条指令地址 |
---------------------------------------------------------
| 上一个函数r14的值 |
---------------------------------------------------------
| 进入函数体后的PC值(XSCALE 中为PC+ 0X8) 因为三级流水线|
内存高地址 --------------------------------------------------------- <--------栈底(r11)
2:首先压栈过程是由高地址到低地址的;
3:函数传递参数由左到右;
4:局部变量的压入过程为定义的顺序;
几点说明:
1,存储当前PC的时候,实际指令为PC+ 0X8
ARM7TDMI-S 处理器使用流水线来增加处理器指令流的速度这样可使几个操作同时进行并使处理和存储器系统连续操作,流水线使用3 个阶段因此指令分3 个阶段执行
Ø 取指
Ø 译码
Ø 执行
3 阶段流水线如图所示
注程序计数器(PC)指向被取指的指令而不是指向正在执行的指令
在正常操作过程中在执行一条指令的同时对下一条指令进行译码并将第三条指令从存储器中取出
相关参考资料:
ARM7中寄存器对应表:
R0 R0
.. ..
R9 R9
R10 ---> SL
R11 ---> FP FRAME POINTER 基址指针指向堆栈栈底
R12 ---> IP
R13 ---> SP STACK POINTER 堆栈指针的寄存器(SP)指向堆栈的栈顶
R14 ---> LR
R15 ---> PC
栈的图例(stack-->arm7.cpp):
ARM7在gcc 2.95/2.97编译下使用r11寄存器作为函数栈底指针,r13为当前函数栈顶指针
一个典型的函数栈信息结构为:
内存高地址
------------------------------
| 当前函数的参数 |
--- ------------------------- <--------上一个函数栈顶(r12)
| 进入函数体后的PC值(无用) |
----------------------------- <--------栈底(r11)
函 | 当前函数返回地址 |
------------------------------
数 | 上一个函数13寄存器值 |
------------------------------
堆 | 上一个函数r11寄存器值 |
------------------------------
栈 | 当前函数的局部变量 |
------------------------------
| 传递给下一函数的参数 |
--- ------------------------- <--------栈顶(r13)
内存低地址
(注意直接取r11值将取PC值,而非函数返回地址)
--------------------------------------------------------------------------------------
以文本方式查看主题
1、堆/栈
我想这里的很多的兄弟同我一样吧,都没有系统的学习过操作系统的理论,不过
也许是我估计错误吧,见笑。
接触微处理,是从简单的8051开始的,那时候的程序写起来同现在有很大的不同。
尤其在堆栈的处理,其实汇编的堆栈同处理器的支持是直接相关,但是在使用C下
的堆栈有些东西就需要特殊处理。
通常堆栈只是一个集体的名词,堆应该是存放处理器状态,或者程序运行状态的
部分,栈应该是用来进行动态内存分配的内存区域malloc(这是C下的理解)
堆栈通常按照高低地址增长的方向和指针指向的位置划分:
增长:从低地址向高地址
递减:从高地址向的地址
================
指针sp位置,如果指向最后存放数据的地址,称为满堆栈如果指向空的地址,成为
空堆栈
各种处理器会支持者2*2=4中不同类型的堆栈。
2、关于arm的堆栈:
arm是risc的机器没有自己的push pop 指令,通常使用stm LDM指令完成压入弹
出操作。arm的使用r13=sp ,r14=lR ,r15=pc
当然在不同的模式下后又不同的影子寄存器,这里的影子是说,他们虽然使用了
同样的名称,但是实际的物理地址不是相同的空间,只是认为的做了一些关系的MAP。
因为这样可以加速数据的处理。
3、同arm相关的通常是!,S,^这些比较特殊的东西,
尤其对于LDR指令而言,在使用前偏移地时候就有了!,这同后偏移不同
前【Rn,Rm,#**】 这种类型是先进行偏移然后加载数据,更具是否!更新Rn
后【Rn】,Rm,#×× 这是先加载数据,然后进行偏移,一定更新Rn
S通常是一个时候更新标志,有时候如果存在PC(r15)加载的话,会作为更新cpsr
的选项, ^这个用到的时候通常不多。这也是同cpsr,spsr相关的东西。
4流水线
这是因为ARM是3级流水线运行,通常运行的指令是Pc-8也就是说运行的指令不是
当前的pc指针值。
5、 异常处理部分:
异常处理是同模式相关的一个概念,ARM有多种异常,对应不同的模式,但是他
们之间不是一一对应的关系。
返回与否?
有些异常是不需要返回的,reset
其他的异常通常是需要返回到以前的状态 abort,但是不同的异常返回的点是不
同的。通常异常的时候会保存下一个指令的地址到R14这样,就需要在返回的时候更具需要进行调整你的PC。
,返回后通常执后的下一条指令这样使用 movs就足够了
abort,就需要返回出现问题的那条指令,也就是【R14】-4 了,所以通常使用subs返回。
一些小的理解,希望交流,如有不对之处,请更正。
--
ARM7是三级的,ARM9好象就是5级的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步