zl程序教程

您现在的位置是:首页 >  后端

当前栏目

[C语言]函数栈帧的创建和销毁

C语言 函数 创建 销毁 栈帧
2023-06-13 09:18:27 时间

函数栈帧的创建和销毁::

  ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的,edp被称为栈底指针,esp被称为栈顶指针。push:压栈:给栈顶放一个元素。pop:出栈:给栈顶删一个元素,lea:加载有效地址。dword=4byte。

int Add(int x,int y)
{
    push    ebp
    mov     ebp,esp
    push    ebx
    push    esi
    push    edi
    lea     edi [ebp+FFFFFF34h]
    mov     ecx,33h
    mov     eax,0CCCCCCCh
    rep     stos dword ptres:[edi]
int z = 0;
    mov     dword ptr[ebp-8] 0
z = x + y;
    mov     eax,dword ptr [ebp+8]
    add     eax,dword ptr [ebp+0Ch]
    mov     dword ptr [ebp-8] eax
    mov     eax,dword ptr [ebp-8]
    pop     edi
    pop     esi
    pop     ebx
    mov     ebp,esp
    pop     ebp
    ret
}
int main()
{
    push    ebp
    mov     ebp,esp
    sub     esp,0E4h
    push    ebx
    push    esi
    push    edi
    lea     edi,[ebp-0E4h]     
    mov     ecx,39h
    mov     eax,0ccccccch
    rep     stos dword ptr es:[edi]
int a = 10;
    mov     dword ptr[ebp-8],0Ah
int b = 20;
    mov     dword ptr[ebp-14h],14h
int c = 0;
    mov     dword ptr[ebp-20h],0
c = Add(a,b);
    mov     eax,dword ptr [ebp-14h]
    push    eax
    mov     ecx,dword ptr [ebp-8]
    push    ecx
    call    00C210E1
    add     esp,8                            00C21450
    mov     dword ptr[ebp-20h],eax
printf("%d\n",c);
    mov     esi,esp
    mov     eax,dword ptr[ebp-20h]
    push    eax
    push    0C25858h
    call    dword ptr ds:[00C29114]
    add     esp,8
    cmp     esi,esp
    cabl    00C2133B
return 0;
}

解决问题:

1.局部变量是怎么创建的?

答:首先为此次函数调用创建函数栈帧,在函数栈帧找空间存放局部变量值。

2.为什么局部变量的值是随机值?

随机值是系统开辟完函数栈帧后系统随机放进去的。

3.函数是怎么传参的?

形参在刚开始调用之前就已经传过去了,形式参数从左向右传递。

4.形参和实参是什么关系?

形参是实参的临时拷贝,值相同但空间不同,因此改变形参的值不会影响实参的值。

5.函数调用结束后怎么返回的?

返回值并不会随着函数作用域的销毁而销毁,而是放在eax中准备返回,当通过pop出栈回到main函数中再将返回值放到局部变量中。

C语言编程训练

1.编写程序将三个整数从大到小输出

#include<stdio.h> 
代码1
	int main()
	{
		int a = 0;
		int b = 0;
		int c = 0;
		int temp = 0;
		scanf("%d %d %d", &a, &b, &c);
		if (a < b)
		{
			temp = a;
			a= b;
			b = temp;
		}
		if (a < c)
		{
			temp = a;
			a = c;
			c = temp;
		}
		if (b < c)
		{
			temp = b;
			b = c;
			c = temp;
		}
		printf("%d %d %d", a, b, c);
		return 0;
    }
代码2:函数版
Swap(int* px, int* py)
{
	int temp = *px;
	*px = *py;
	*py = temp;
}
int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	scanf("%d %d %d", &a, &b, &c);
	if (a < b)
	{
		Swap(&a, &b);
	}
	if (a < c)
	{
		Swap(&a, &c);
	}
	if (b < c)
	{
		Swap(&b, &c);
	}
	printf("%d %d %d", a, b, c);
	return 0;
}

2.编写程序打印1—100之间所有3的倍数的数字

#include<stdio.h>
打印1-100之间所有3的倍数的数字
代码1
int main()
{
	int i = 0;
	for (i = 1; i <= 100; i++)
	{
		if (i % 3 == 0)
			printf("%d ", i);
	}
	return 0;
}
 代码2
int main()
{
  int i = 0;
	for (i = 3; i <= 100; i += 3)
	{
		printf("%d ", i);
	}
	return 0;
}

3.编写程序求两个数的最大公约数

#include<stdio.h> 
求两个数的最大公约数
 代码1
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int min = (a < b ? a : b);
	int m = min;
	while (1)
	{
		if (a % m == 0 & b % m == 0)
		{
			break;
		}
		m--;
	}
	printf("%d\n", m);
	return 0;
}
代码2
辗转相除法:24 % 18 == 6  18 % 6 == 0
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	while (a % b)
	{
		int c = a % b;
		a = b;
		b = c;
	}
	printf("%d\n", b);
	return 0;
}
优化
int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	scanf("%d %d", &a, &b);
	while (c = a % b)
	{
		a = b;
		b = c;
	}
	return 0;
}

4.编写程序计算1/1-1/2+1/3-1/4+1/5+......+1/99-1/100

#include<stdio.h>
int main()
{
	int i = 0;
	double sum = 0.0;
	int flag = 1;
	for (i = 1; i <= 100; i++)
	{
		sum = sum + flag*(1.0 / i);//一定不能写成1/i
		flag = -flag;//不能写成flag=-1
	}
	printf("%lf\n", sum);
	return 0;
}

5.求十个整数中最大值

#include<stdio.h>
代码1
int main()
{
	//准备10个整数
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//找出最大值
	int i = 0;
	int max = arr[0];//max不能赋值成0来比较负数 
	for (i = 1; i < 10; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	printf("%d\n",max);
	return 0;
}
代码2
int main()
{
    int arr[10] = {0};
    //输入数字
	int n = 0;
    for(n = 0;n < 10;n++)
{
        scanf("%d",&arr[n]);
}
	//找出最大值
	int i = 0;
	int max = arr[0];//max不能赋值成0来比较负数 
	for (i = 1; i < 10; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	printf("%d\n",max);
	return 0;
}

6.打印九九乘法口诀表

#include<stdio.h>
代码1
int main()
{
	int i = 0;
	for (i = 1; i <= 9; i++)
	{
		int j = 0;
		for (j = 1; j <= i; j++)
		{
			printf("%d*%d=%-2d ", i,j, i * j);
		}
		printf("\n");
	}
	return 0;
}
代码2
int main()
{
	int i = 0;
	for (i = 1; i <= 9; i++)
	{
		int j = 0;
		for (j = 1; j <= i; j++)
		{
			printf("%d*%d=%-2d ", j,i, i * j);
		}
		printf("\n");
	}
	return 0;
}

补:编写程序打印1到100之间数字9出现的个数

#include<stdio.h>
int main()
{
	int i = 0;
	int count = 0;//计数
	for (i = 1; i <= 100; i++)
	{
		if (i % 10 == 9)//判断个位是不是9
			count++;
		if (i / 10 == 9)//判断十位是不是9
			count++;
	}
	printf("count=%d\n", count);
	return 0;
}

7.实现一个函数来打印乘法口诀表,行数列数自己指定

#include<stdio.h>
void print_table(int n)
{
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		int j = 0;
		for (j = 1; j <= i; j++)
		{
			printf("%d*%d=%-2d ", j, i, i * j);
		}
		printf("\n");
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	print_table(n);
	return 0;
}