编程范式(斯坦福大学)学习笔记《十》

int foo(int bar,int* baz)
{
 char snink[4];
 short* why;
 }

栈段示意图:

注意
1.局部变量参数根据声明从右至左而在栈中从高地址至低地址存放,即,第0个参数(bar)总是放在其他参数的下方,第1个参数在第0个参数之上。空间位域参数位于局部变量下方(也就是位于低地址处)。在空间位域参数和局部变量之间存储着调用函数的某些信息,以便告诉我们到底是哪块代码调用了这个函数(foo)。

函数调用:

int main(int argc, char** argv)
{
int i=4;
foo(i,&i);
    return 0;
}

对应的汇编代码:

SP=SP-4;
M[sp]=4;

SP=SP-8;
R1=M[SP+8];
R2=SP+8;
M[SP]=R1;//i
M[SP+4]=R2;//&i

CALL<foo>;//跳转指令
SP=SP+8;//这个值就是saved pc

栈段示意图:

注意

1.SP(stack pointer)是一个特定的寄存器,这个寄存器总是指向执行中的栈的最低地址,因此当main调用时,sp指向saved PC。

2.每条汇编语句都默认为4字节。

补充完整的foo函数:

int foo(int bar,int* baz)
{
 char snink[4];
 short* why;
 why=(short *)(snink+2);
 *why=50;
 return 0;
 }

对应的汇编代码:

<foo>
//为局部变量留空间
SP=SP-8
//没有初始化
R1=SP+6;
M[SP]=R1;//将snink[2]的地址读入寄存器中
R1=M[SP];
M[R1]=.2 50;
SP=SP+8//SP指向返回地址
RET;//return这条指令把SP的值取出来放到PC,同时SP+=4

一般栈段内的活动记录示意图:

这个活动记录使得函数能够执行并且让它可以访问所有的参数和局部变量。

活动纪律被分为用户调用函数部分和被调用函数部分这两部分的原因:因为调用者并不知道上面例子中的foo函数在实现过程中有多少局部变量。



int fact(int n)
{
    if(n==0)
        return 1;
    return n*fact(n-1);
}

对应的汇编代码:

<fact>
R1=M[SP+4];
BNE R1,0,PC+12//若条件不成立,跳出if语句,也就是三行汇编代码(3*4)
RV=1;
RET;

R1=M[SP+4];
R1=R1-1;
SP=SP-4;
M[SP]=R1;
CALL<fact>;
SP=SP+4;//回收局部变量空间
R1=M[SP+4]
RV*R1;
RV;

注意

在汇编语言中,处理PC,SP,还有一个寄存器叫做RV,RV寄存器专门用来在调用者和被调用函数之间传递返回值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值