sparc v8 stack frame calling convention

main.c

int enable=1;

int main()
{
    int a, b;
    int sum;
    
    a = 1;
    b = 3;
    
    sum = add(a, b);
    
    return 0;
}

int add(int a, int b)
{
    int x, y;
    x = a;
    y = b;
    return (x+y);
}

int del()
{
    return 0;
}
View Code

 

汇编如下:

main.elf:     file format elf32-sparc

Disassembly of section .text:

70000000 
: 70000000: 9d e3 bf 88 save %sp, -120, %sp 70000004: 90 10 20 01 mov 1, %o0 70000008: d0 27 bf f4 st %o0, [ %fp + -12 ] 7000000c: 90 10 20 03 mov 3, %o0 70000010: d0 27 bf f0 st %o0, [ %fp + -16 ] 70000014: d0 07 bf f4 ld [ %fp + -12 ], %o0 70000018: d2 07 bf f0 ld [ %fp + -16 ], %o1 7000001c: 40 00 00 08 call 7000003c 70000020: 01 00 00 00 nop 70000024: d0 27 bf ec st %o0, [ %fp + -20 ] 70000028: 90 10 20 00 clr %o0 7000002c: b0 10 00 08 mov %o0, %i0 70000030: 01 00 00 00 nop 70000034: 81 c7 e0 08 ret 70000038: 81 e8 00 00 restore 7000003c : 7000003c: 9d e3 bf 90 save %sp, -112, %sp 70000040: f0 27 a0 44 st %i0, [ %fp + 0x44 ] 70000044: f2 27 a0 48 st %i1, [ %fp + 0x48 ] 70000048: f0 07 a0 44 ld [ %fp + 0x44 ], %i0 7000004c: f0 27 bf f4 st %i0, [ %fp + -12 ] 70000050: f0 07 a0 48 ld [ %fp + 0x48 ], %i0 70000054: f0 27 bf f0 st %i0, [ %fp + -16 ] 70000058: f2 07 bf f4 ld [ %fp + -12 ], %i1 7000005c: f0 07 bf f0 ld [ %fp + -16 ], %i0 70000060: b0 06 40 18 add %i1, %i0, %i0 70000064: 01 00 00 00 nop 70000068: 81 c7 e0 08 ret 7000006c: 81 e8 00 00 restore 70000070 : 70000070: 9d e3 bf 98 save %sp, -104, %sp 70000074: b0 10 20 00 clr %i0 70000078: 01 00 00 00 nop 7000007c: 81 c7 e0 08 ret 70000080: 81 e8 00 00 restore Disassembly of section .data: 70000084 : 70000084: 00 00 00 01 unimp 0x1
View Code

混合源程序的反汇编如下:局部变量的定义不会增加程序指令。

main.elf:     file format elf32-sparc

Disassembly of section .text:

70000000 
: int enable=1; int main() { 70000000: 9d e3 bf 88 save %sp, -120, %sp int a, b; int sum; a = 1; 70000004: 90 10 20 01 mov 1, %o0 70000008: d0 27 bf f4 st %o0, [ %fp + -12 ] b = 3; 7000000c: 90 10 20 03 mov 3, %o0 70000010: d0 27 bf f0 st %o0, [ %fp + -16 ] sum = add(a, b); 70000014: d0 07 bf f4 ld [ %fp + -12 ], %o0 70000018: d2 07 bf f0 ld [ %fp + -16 ], %o1 7000001c: 40 00 00 08 call 7000003c 70000020: 01 00 00 00 nop 70000024: d0 27 bf ec st %o0, [ %fp + -20 ] return 0; 70000028: 90 10 20 00 clr %o0 } 7000002c: b0 10 00 08 mov %o0, %i0 70000030: 01 00 00 00 nop 70000034: 81 c7 e0 08 ret 70000038: 81 e8 00 00 restore 7000003c : int add(int a, int b) { 7000003c: 9d e3 bf 90 save %sp, -112, %sp 70000040: f0 27 a0 44 st %i0, [ %fp + 0x44 ] 70000044: f2 27 a0 48 st %i1, [ %fp + 0x48 ] int x, y; x = a; 70000048: f0 07 a0 44 ld [ %fp + 0x44 ], %i0 7000004c: f0 27 bf f4 st %i0, [ %fp + -12 ] y = b; 70000050: f0 07 a0 48 ld [ %fp + 0x48 ], %i0 70000054: f0 27 bf f0 st %i0, [ %fp + -16 ] return (x+y); 70000058: f2 07 bf f4 ld [ %fp + -12 ], %i1 7000005c: f0 07 bf f0 ld [ %fp + -16 ], %i0 70000060: b0 06 40 18 add %i1, %i0, %i0 } 70000064: 01 00 00 00 nop 70000068: 81 c7 e0 08 ret 7000006c: 81 e8 00 00 restore 70000070 : int del() { 70000070: 9d e3 bf 98 save %sp, -104, %sp return 0; 70000074: b0 10 20 00 clr %i0 } 70000078: 01 00 00 00 nop 7000007c: 81 c7 e0 08 ret 70000080: 81 e8 00 00 restore
View Code

 

1、3个局部变量,共12字节,按照8字节对齐,需要16字节,即104+16=120

70000000: 9d e3 bf 88 save  %sp, -120, %sp

2、main.c将局部变量a,b分配在%fp + -12,%fp + -16

70000004:    90 10 20 01     mov  1, %o0
70000008:    d0 27 bf f4     st  %o0, [ %fp + -12 ]
7000000c:    90 10 20 03     mov  3, %o0
70000010:    d0 27 bf f0     st  %o0, [ %fp + -16 ]

3、将输入参数放在o0和o1中,然后调用add

70000014:    d0 07 bf f4     ld  [ %fp + -12 ], %o0
70000018:    d2 07 bf f0     ld  [ %fp + -16 ], %o1
7000001c:    40 00 00 08     call  7000003c 

4、将局部变量sum,放在%fp + -20,调用结束,从o0取得add的返回值。

70000024:    d0 27 bf ec     st  %o0, [ %fp + -20 ]

5、add现将i0和i1放在%fp + 0x44,%fp + 0x48,这是为什么?0x44=68, 0x48=72

70000040:    f0 27 a0 44     st  %i0, [ %fp + 0x44 ]
70000044:    f2 27 a0 48     st  %i1, [ %fp + 0x48 ]

6、然后,赋值局部变量

70000048:    f0 07 a0 44     ld  [ %fp + 0x44 ], %i0
7000004c:    f0 27 bf f4     st  %i0, [ %fp + -12 ]
70000050:    f0 07 a0 48     ld  [ %fp + 0x48 ], %i0
70000054:    f0 27 bf f0     st  %i0, [ %fp + -16 ]

 

add函数里的%fp + 0x44感觉又到了main的堆栈里了,这是怎么回事?见下面分析。

sparc v8 stack frame calling convention_第1张图片

 

The caller’s stack pointer %sp (%o6) automatically becomes the current procedure’s frame pointer %fp (%i6) when the SAVE instruction is executed.

SAVE同时也具有ADD的效果。

 

3803手册中,%fp + 0x44位置处写着,用于存储被调函数的寄存器变量,也就是add函数。在调用函数的堆栈中,为什么要存储被调函数的东西呢?见下面分析

sparc v8 stack frame calling convention_第2张图片

 System V Application Binary Interface - SPARC Processor Supplement -3dt,p24描述如下:

Although the first 6 words of arguments reside in registers, the standard stack frame reserves space
for them. ‘‘Coding Examples’’ below explains how these words may be used to implement variable
argument lists. Arguments beyond the sixth reside on the stack.

虽然前6个参数放在寄存器中,但是标准的栈帧也给它们预留了空间。

下面图来自abi_sparc,p24。

其中previous帧中说six words into which function may write incoming arguments 0 to 5,这是里may可能,调用函数可能将前6个输入参数既放入i0~i5,又放在这里。

current帧中说six words into which callee may write outgoing arguments 0 to 5,这是里may可能,被调函数可能将前6个输出参数既放入i0~i5,又放在这里。

但从实际sparc-elf-gcc的使用来看,被调函数做了调用函数的工作,即被调函数将输入参数i0~i5放在了调用函数栈帧的该位置处。

sparc v8 stack frame calling convention_第3张图片

 

reference:

SYSTEM V APPLICATION BINARY INTERFACE, SPARC Processor Supplement, Third Edition

链接:https://pan.baidu.com/s/1lRCz7Z0nol-8gOzed3Rmyw
提取码:0kjr

BM3803MGRH用户手册

链接:https://pan.baidu.com/s/1T3sNflIAdCUGGcON3-tWpQ
提取码:xkty
复制这段内容后打开百度网盘手机App,操作更方便哦

 

你可能感兴趣的:(sparc v8 stack frame calling convention)