PPC E500内核寄存器

本文深入探讨了C语言编程中帧栈的自动管理过程,并通过汇编语言展示了如何手动维护帧栈结构。从ABI手册出发,解释了C语言中参数传递、返回值存储以及临时变量使用的规则。同时,通过代码示例和汇编输出对比,直观展示了C编译器如何生成汇编代码以实现帧栈的高效管理。最后,强调了在使用汇编语言时需要自行维护帧栈的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ABI手册中规定用户编程是需要注意的:

1.r0  存放LR寄存器的值,即函数的返回地址。

2.r1  PPC处理器没有在指令级别上支持堆栈,没有专门的堆栈类寄存器,ABI规定使用r1保存栈顶指针。

3.r3-r4 存放程序的返回值。

4.r3-r10 用来传递函数的参数,不够则使用堆栈进行传递,尽量控制在8个参数范围内这样可以提高函数的调用效率。

5.r13 用来存放数据段的基地址。

6.r14-r31 用来存放临时变量的,程序员可以自用使用。

 

如下是一个测试函数:

#include <stdio.h>

#define ONE 1
int justForTest(int a,int b,int c)
{
 int t1=0,t2=0,t3=0;
 
 t1 += a;
 t2 += b;
 t3 += c; 
 t3 += ONE;
 
 return t3;
}

 

执行ccppc -E d:/test.c 进行预编译后的结果:

/*头文件进行了展开*/

int justForTest(int a,int b,int c)
{
        int t1=0,t2=0,t3=0;


        t1 += a;
        t2 += b;
        t3 += c;
        t3 += 1 ;  //只是对宏进行了简单的替换

        return t3;
}

 

执行ccppc -S d:/test.c生成的汇编代码:

 .file "test.c"
gcc2_compiled.:
 .section ".text"
 .align 2
 .globl justForTest
 .type  justForTest,@function
justForTest:
 stwu 1,-48(1)  /*stwu RS,D(RA)与stw RS,D(RA)格式一样,只是它执行后会将RA寄存器的值更新为RA+D。这里可以看出来

                          每一个帧栈结构占有48个字节,把r1的值存到了栈顶*/
 stw 31,44(1)  /*r31中存放了指向前一个帧栈的指针,即上一个帧栈的栈顶*/
 mr 31,1         /*把栈顶指针拷贝到r31中*/
 stw 3,8(31)    /*r3、r4、r5用来保存函数的参数,把三个参数压入堆栈*/
 stw 4,12(31)
 stw 5,16(31)
 li 0,0
 stw 0,20(31)
 li 0,0
 stw 0,24(31)
 li 0,0
 stw 0,28(31)
 lwz 0,20(31)
 lwz 9,8(31)
 add 0,0,9
 stw 0,20(31)
 lwz 0,24(31)
 lwz 9,12(31)
 add 0,0,9
 stw 0,24(31)
 lwz 0,28(31)
 lwz 9,16(31)
 add 0,0,9
 stw 0,28(31)
 lwz 9,28(31)
 addi 0,9,1
 stw 0,28(31)
 lwz 0,28(31)
 mr 3,0           /*把函数的返回值写入到r3*/
 b .L2
.L2:
 lwz 11,0(1)
 lwz 31,-4(11)    /*保留指向当前帧栈的指针到r31,以便下一个帧栈用来形成一个帧栈链表用*/
 mr 1,11
 blr
.Lfe1:
 .size  justForTest,.Lfe1-justForTest
 .ident "GCC: (GNU) gcc-2.96 (2.96+ MW/LM) 19990621 AltiVec VxWorks 5.5"

 

还可以通过反汇编的方式获取汇编代码objdumpppc -d test.o > 1这样获得的汇编代码看起来更容易懂

test.o:     file format elf32-powerpc

Disassembly of section .text:

00000000 <justForTest>:
   0: 94 21 ff d0  stwu r1,-48(r1)
   4: 93 e1 00 2c  stw r31,44(r1)
   8: 7c 3f 0b 78  mr r31,r1
   c: 90 7f 00 08  stw r3,8(r31)
  10: 90 9f 00 0c  stw r4,12(r31)
  14: 90 bf 00 10  stw r5,16(r31)
  18: 38 00 00 00  li r0,0
  1c: 90 1f 00 14  stw r0,20(r31)
  20: 38 00 00 00  li r0,0
  24: 90 1f 00 18  stw r0,24(r31)
  28: 38 00 00 00  li r0,0
  2c: 90 1f 00 1c  stw r0,28(r31)
  30: 80 1f 00 14  lwz r0,20(r31)
  34: 81 3f 00 08  lwz r9,8(r31)
  38: 7c 00 4a 14  add r0,r0,r9
  3c: 90 1f 00 14  stw r0,20(r31)
  40: 80 1f 00 18  lwz r0,24(r31)
  44: 81 3f 00 0c  lwz r9,12(r31)
  48: 7c 00 4a 14  add r0,r0,r9
  4c: 90 1f 00 18  stw r0,24(r31)
  50: 80 1f 00 1c  lwz r0,28(r31)
  54: 81 3f 00 10  lwz r9,16(r31)
  58: 7c 00 4a 14  add r0,r0,r9
  5c: 90 1f 00 1c  stw r0,28(r31)
  60: 81 3f 00 1c  lwz r9,28(r31)
  64: 38 09 00 01  addi r0,r9,1
  68: 90 1f 00 1c  stw r0,28(r31)
  6c: 80 1f 00 1c  lwz r0,28(r31)
  70: 7c 03 03 78  mr r3,r0
  74: 48 00 00 04  b 78 <justForTest+0x78>
  78: 81 61 00 00  lwz r11,0(r1)
  7c: 83 eb ff fc  lwz r31,-4(r11)
  80: 7d 61 5b 78  mr r1,r11
  84: 4e 80 00 20  blr

 

     总之,使用C语言时不需要考虑对帧栈的维护,整个帧栈机构的维护由C编译器完成。但是汇编语言中必须自己来维护,可以先使用C语言写一个函数的基本架子,将所有的函数参数、变量都写进去,然后使用C编译器生成汇编代码,此时生成的汇编代码将能自动维护帧栈结构了。

### PowerPC 架构寄存器使用规范和约定 PowerPC 架构定义了一组寄存器使用规范,这些规范由 EABI(Extended Application Binary Interface)标准所支持,确保编译器、操作系统和应用程序之间在寄存器使用上的统一性。该规范涵盖了寄存器的用途、堆栈结构以及函数调用的参数传递规则等关键内容[^3]。 #### 通用寄存器(GPR) PowerPC 处理器提供 32 个通用寄存器(GPR),每个寄存器可以是 32 位或 64 位宽,具体取决于实现。这些寄存器在函数调用中具有特定的用途[^5]: - **r0**:通常用于保存函数调用前的链接寄存器(LR)值,也可作为临时寄存器。 - **r1**:栈指针(Stack Pointer),用于指向当前函数的栈帧顶部。 - **r2**:表内容指针(Table of Contents Pointer),用于访问全局数据。 - **r3**:常用于保存函数的返回值,同时也是第一个函数参数的传递寄存器。 - **r4–r10**:用于传递函数的第 2 到第 8 个参数。 - **r11–r12**:本地临时寄存器,用于函数内部的临时计算。 - **r13–r31**:全局寄存器,调用函数时必须保存其值。 #### 专用寄存器 除了通用寄存器,PowerPC 还包括多个专用寄存器: - **PC(程序计数器)**:也称为 IAR(指令地址寄存器)或 NIP(下一指令指针),用于指示当前执行的指令地址。 - **LR(链接寄存器)**:保存函数调用返回地址,不能直接作为通用寄存器使用,需通过 `mflr` 和 `mtlr` 指令操作。 - **CR(条件寄存器)**:用于保存比较和条件分支的结果,包含多个字段,每个字段可以独立设置。 #### 浮点寄存器(FPR) 某些 PowerPC 实现(如 MPC555)支持 32 个 64 位浮点寄存器(FPR),用于浮点运算。这些寄存器在浮点函数调用中也有特定的使用约定[^2]。 #### 参数传递规则 PowerPC 的 EABI 规范定义了函数调用时参数的传递方式: - 前八个整数或指针参数通过寄存器 `r3` 到 `r10` 传递。 - 超过八个参数的函数调用则将额外的参数压入栈中。 - 浮点参数通过浮点寄存器 `f1` 到 `f13` 传递,超出部分同样压入栈中[^3]。 #### 函数返回值 - 整数或指针类型的返回值通过 `r3` 寄存器返回。 - 浮点类型的返回值通过 `f1` 寄存器返回。 #### 示例:函数调用中的寄存器使用 ```asm # 示例:调用一个带有两个参数的函数 li r3, 10 # 第一个参数 li r4, 20 # 第二个参数 bl some_function # 调用函数 ``` ### 相关问题 1. PowerPC 架构中如何通过寄存器进行函数参数传递? 2. EABI 规范对 PowerPC 寄存器的使用有哪些具体要求? 3. PowerPC 架构中浮点寄存器的使用规则是什么? 4. 如何在 PowerPC 中实现栈帧的构建与恢复? 5. PowerPC 中 LR 寄存器在函数调用中起什么作用?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值