函数调用栈

函数调用栈帧过程(带图详解) 函数调用我们大家都很熟悉,我们都知道函数调用是发生在栈上的。首先,我们来了解一下程序对内存使用的分区情况: 区域 作用 栈区(stack) 由编译器自动分配和释放,存放函数的参数值,局部变量的值等。操作方式类似与数据结构中的栈 堆区(heap) 一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。与数据结构中的堆是两码事,分配方式类似于链表 静态区(sta 阅读详情

函数调用栈

什么是函数调用栈

函数是每一门编程语言中,不可缺少的部分。函数本质是一片成块的内存指令。而函数调用,除了基本的程序指令跳转外,还需要保存函数相关的上下文,也就是函数的参数,本地变量,返回参数,返回地址等。保存函数上下文的就是我们常说的函数栈。函数相互调用的栈结构,就是函数调用栈。

函数调用栈用在何处

  1. 函数调用栈是函数调用必不可少的组成部分。
  2. 我们常说的协程,底层的实现原理,都是基于函数调用栈的。协程切换,就是不同的栈帧切换,同时保存相关的上下文,当然这里也有寄存器值的保存。

C语言实现

#include <stdio.h>

int sum(int a, int b, int c) {
    int sum_loc1 = 7;
    int sum_loc2 = 8;
    int sum_loc3 = 9;
    
    return sum_loc1 + sum_loc2 + sum_loc3 + a + b + c;
}

int main(int argc, const char *argv[]) {
    int loc1 = 1;
    int loc2 = 2;
    int loc3 = 3;
    int ret = sum(4,5,6);
    printf("ret:%d\n", ret);
}
  • C语言对应的x86_64汇编代码
0000000000400530 <sum>:
  400530:	55                   	push   %rbp               # rbp 入栈
  400531:	48 89 e5             	mov    %rsp,%rbp          # rbp = rsp
  400534:	89 7d ec             	mov    %edi,-0x14(%rbp)   # 第一个参数入栈
  400537:	89 75 e8             	mov    %esi,-0x18(%rbp)   # 第二个参数入栈
  40053a:	89 55 e4             	mov    %edx,-0x1c(%rbp)   # 第三个参数入栈
  40053d:	c7 45 fc 07 00 00 00 	movl   $0x7,-0x4(%rbp)    # 本地变量1:7
  400544:	c7 45 f8 08 00 00 00 	movl   $0x8,-0x8(%rbp)    # 本地变量2:8 
  40054b:	c7 45 f4 09 00 00 00 	movl   $0x9,-0xc(%rbp)    # 本地变量3:9
  400552:	8b 45 f8             	mov    -0x8(%rbp),%eax
  400555:	8b 55 fc             	mov    -0x4(%rbp),%edx
  400558:	01 c2                	add    %eax,%edx          # 8 + 7
  40055a:	8b 45 f4             	mov    -0xc(%rbp),%eax
  40055d:	01 c2                	add    %eax,%edx          # 9 + 15 = 24
  40055f:	8b 45 ec             	mov    -0x14(%rbp),%eax   # 4 + 24 = 28
  400562:	01 c2                	add    %eax,%edx
  400564:	8b 45 e8             	mov    -0x18(%rbp),%eax   # 5 + 28 = 33
  400567:	01 c2                	add    %eax,%edx
  400569:	8b 45 e4             	mov    -0x1c(%rbp),%eax   # 6 + 33 = 39
  40056c:	01 d0                	add    %edx,%eax          # eax 作为返回值存储寄存器
  40056e:	5d                   	pop    %rbp               # 弹出rbp
  40056f:	c3                   	retq   

0000000000400570 <main>:
  400570:	55                   	push   %rbp                # rbp 压栈
  400571:	48 89 e5             	mov    %rsp,%rbp           # rbp = rsp
  400574:	48 83 ec 20          	sub    $0x20,%rsp          # rsp = 32 ; 字节
  400578:	89 7d ec             	mov    %edi,-0x14(%rbp)    #  
  40057b:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)    #
  40057f:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)     # 本地变量从右到左入栈
  400586:	c7 45 f8 02 00 00 00 	movl   $0x2,-0x8(%rbp)     # 
  40058d:	c7 45 f4 03 00 00 00 	movl   $0x3,-0xc(%rbp)     #
  400594:	ba 06 00 00 00       	mov    $0x6,%edx           # 第三个参数
  400599:	be 05 00 00 00       	mov    $0x5,%esi           # 第二个参数
  40059e:	bf 04 00 00 00       	mov    $0x4,%edi           # 第一个参数
  4005a3:	e8 88 ff ff ff       	callq  400530 <sum>        # 调用sum指令
  4005a8:	89 45 f0             	mov    %eax,-0x10(%rbp)    # 返回值放入预先的栈空间
  4005ab:	8b 45 f0             	mov    -0x10(%rbp),%eax
  4005ae:	89 c6                	mov    %eax,%esi           # 放入printf第二个参数
  4005b0:	bf 60 06 40 00       	mov    $0x400660,%edi
  4005b5:	b8 00 00 00 00       	mov    $0x0,%eax
  4005ba:	e8 51 fe ff ff       	callq  400410 <printf@plt>
  4005bf:	c9                   	leaveq 
  4005c0:	c3                   	retq   
  4005c1:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  4005c8:	00 00 00 
  4005cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)


# call :
# 1. 将call下一条指令入栈;也就是ip入栈 
# 2. 将sum指令入ip
  • 对应的C语言栈帧

在这里插入图片描述

1. 本地变量从左到右依次入栈,返回值保存的变量是第四个本地变量
2. 函数参数由被调用者`callee`负责维护,从左到右依次入栈
3. 最后返回地址入栈
4. `rbp`入栈

Go语言实现

package main

import (
	"fmt"
)

func sum(a, b, c int) (ret1, ret2 int) {
    loc1 := 1
    loc2 := 2
    loc3 := 3
    return a + b + loca1, c + loc2 + loc3
}

func main() {
    l1 := 4
    l2 := 5
    l3 := 6
    r1,r2 := sum(7,8,9)
    fmt.Printf("r1:%d, r2%d\n", r1, r2)
}
func sum(a, b, c int) (ret1, ret2 int) {
  0x49aa80		4883ec30		SUBQ $0x30, SP		     # 栈扩展 48字节
  0x49aa84		48896c2428		MOVQ BP, 0x28(SP)	     # bp 入栈
  0x49aa89		488d6c2428		LEAQ 0x28(SP), BP	     # 重新设置bp的值
  0x49aa8e		48c744245000000000	MOVQ $0x0, 0x50(SP)	 #
  0x49aa97		48c744245800000000	MOVQ $0x0, 0x58(SP)	
	loc1 := 1
  0x49aaa0		48c744241001000000	MOVQ $0x1, 0x10(SP)	 # 本地变量1
	loc2 := 2
  0x49aaa9		48c744240802000000	MOVQ $0x2, 0x8(SP)	
	loc3 := 3
  0x49aab2		48c7042403000000	MOVQ $0x3, 0(SP)	
	return a + b + loc1, c + loc2 + loc3
  0x49aaba		488b442438		MOVQ 0x38(SP), AX	     # caller保存参数
  0x49aabf		4803442440		ADDQ 0x40(SP), AX	     # 
  0x49aac4		4803442410		ADDQ 0x10(SP), AX	     # AX = loc1 + (a+b) 
  0x49aac9		4889442420		MOVQ AX, 0x20(SP)	     # r1 第一个返回参数
  0x49aace		488b442448		MOVQ 0x48(SP), AX	
  0x49aad3		4803442408		ADDQ 0x8(SP), AX	
  0x49aad8		48030424		ADDQ 0(SP), AX		
  0x49aadc		4889442418		MOVQ AX, 0x18(SP)	     # r2 第二个返回参数
  0x49aae1		488b442420		MOVQ 0x20(SP), AX	
  0x49aae6		4889442450		MOVQ AX, 0x50(SP)	
  0x49aaeb		488b442418		MOVQ 0x18(SP), AX	
  0x49aaf0		4889442458		MOVQ AX, 0x58(SP)	
  0x49aaf5		488b6c2428		MOVQ 0x28(SP), BP	
  0x49aafa		4883c430		ADDQ $0x30, SP		
  0x49aafe		c3			RET
  
  
  
func main() {
  0x49ab00		64488b0c25f8ffffff	MOVQ FS:0xfffffff8, CX	
  0x49ab09		488d842448ffffff	LEAQ 0xffffff48(SP), AX	
  0x49ab11		483b4110		CMPQ 0x10(CX), AX	
  0x49ab15		0f8619030000		JBE 0x49ae34		
  0x49ab1b		4881ec38010000		SUBQ $0x138, SP		
  0x49ab22		4889ac2430010000	MOVQ BP, 0x130(SP)	
  0x49ab2a		488dac2430010000	LEAQ 0x130(SP), BP	
	l1 := 4
  0x49ab32		48c744246004000000	MOVQ $0x4, 0x60(SP)	   # 本地变量1
	l2 := 5
  0x49ab3b		48c744245805000000	MOVQ $0x5, 0x58(SP)	   # 本地变量2
	l3 := 6
  0x49ab44		48c744245006000000	MOVQ $0x6, 0x50(SP)	   # 本地变量3
	r1, r2 := sum(7, 8, 9)
  0x49ab4d		48c7042407000000	MOVQ $0x7, 0(SP)	   # 参数
  0x49ab55		48c744240808000000	MOVQ $0x8, 0x8(SP)	   # 参数2
  0x49ab5e		48c744241009000000	MOVQ $0x9, 0x10(SP)	   # 参数3
  0x49ab67		e814ffffff		CALL main.sum(SB)	
  0x49ab6c		488b442418		MOVQ 0x18(SP), AX	
  0x49ab71		4889442470		MOVQ AX, 0x70(SP)	       # r2返回值拷贝
  0x49ab76		488b442420		MOVQ 0x20(SP), AX	
  0x49ab7b		4889442468		MOVQ AX, 0x68(SP)	       # r2返回值拷贝
  0x49ab80		488b442470		MOVQ 0x70(SP), AX	
  0x49ab85		4889442448		MOVQ AX, 0x48(SP)	
  0x49ab8a		488b442468		MOVQ 0x68(SP), AX	
  0x49ab8f		4889442440		MOVQ AX, 0x40(SP)

在这里插入图片描述

总结

C语言和Go语言栈帧,最大的不同就是:

  • 函数参数保存方式,位置不同

    • C使用寄存器传递函数参数,函数参数保存在callee栈帧中
    • Go直接使用栈传递参数,函数参数保存在caller`栈帧中
  • 函数参数排列顺序不同

    • C函数参数从左到右入栈排列
    • Go函数参数从右到左入栈排列
  • 函数返回值处理不同

    • C通过寄存器ax将返回值传给caller, caller当作本地变量
    • Go:caller拷贝callee栈帧中的返回值,写入本栈,返回值从右向左入栈
【C语言】函数栈帧的创建和销毁 函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间是用来存放:函数参数和函数返回值临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)保存上下文信息(包括在函数调用前后需要保持不变的寄存器)栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。 阅读详情

相关推荐

函数调用与栈

文章目录函数调用与栈内存栈调用函数前调用函数时关于寄存器%ebp栈帧函数调用将要结束时函数调用结束后注 函数调用与栈 内存栈   在C语言中函数的调用必须借助于栈。   关于栈是什么就不再做笔记了,但需要注意的是,这里的栈与数据结构中的栈虽然原理相同但并不是一个东西。在这里,栈就是一段计算机内存,只不过这段内存满足数据后进先出的规则。   另外还需要注意的是,内存栈是向下增长的,即栈顶在下、栈底在...

小腿跑乱刀的博客 3862

函数调用栈的过程(图解)

图解函数调用栈的变化过程

m0_63101588的博客 3427

C++函数调用栈

在程序运行过程中,栈用于维护函数调用的上下文,离开了栈,函数调用就无法实现。

码上看世界 2459

栈与函数调用

1、栈和函数调用的基本概念 栈(FIFO):在数据结构中是一个特殊的容器,遵守先入栈的数据后出栈。在计算机系统中是一个具有以上属性的动态内存区域。栈总是向下增长,压栈操作使栈顶地址减小,弹出操作使栈顶地址增大。 每个进程都会有自己的栈空间,而进程中的各个函数也会维护自己本身的一个栈的区域,这个区域包含了函数调用所需要维护的信息,这个区域常常被称为栈帧或活动记录,堆栈帧一般包含如下几个方面: 1、函数返回地址和参数 2、临时变量:包含函数的非静态局部变量以及编译器自动生成的其他临时变量 3、保存存的上下文:包

weixin_44108830的博客 2663

C函数调用栈

《Linux内核完全注释》3.4节:C与汇编程序互相调用 C函数调用机制 大多数CPU上的程序使用栈来支持函数调用操作。栈被用来传递函数参数、存储返回信息、临时保存寄存器原有值以备恢复以及用来存储局部变量。单个函数调用操作所使用的栈部分被称为栈帧,结构如下所示。 栈帧的两端由两个指针来指定:寄存器ebp通常叫做帧指针,而寄存器esp则用作栈指针; 栈指针的值会随着数据的入栈和出栈而一旦,因此函数中对大部分数据的访问都是基于帧指针ebp进行的,帧指针ebp向上可以访问到函数参数,向下可以访问到局部变量等。

weixin_40775703的博客 1401

函数调用时栈是如何变化的?

大家都知道函数调用是通过栈来实现的,而且知道在栈中存放着该函数的局部变量。但是对于栈的实现细节可能不一定清楚。本文将介绍一下在Linux平台下函数栈是如何实现的。栈帧的结构 函数在调用的时...

编程与实战的博客 3497

函数调用栈是什么

函数调用栈是什么

林隐的博客 1404

C++函数调用栈分布详解

本文详细讲述C++函数调用时的栈分布情况。

dvlinker的技术专栏 5万+

栈的基础知识-函数调用栈的过程图解

栈的基础知识 eip寄存器 存放的指针指向程序即将执行到的地址 esp(32位)/rsp(64位)寄存器 存放函数的栈顶指针 ebp/rbp寄存器 存放函数的栈底指针 函数调用栈 过程 •函数调用栈是指程序运行时内存一段连续的区域 •用来保存函数运行时的状态信息,包括函数参数与局部变量等 •称之为“栈”是因为发生函数调用时,调用函数(caller)的状态被保存在栈内,被调用函数(callee)的状态被压入调用栈的栈顶 •在函数调用结束时,栈顶的函数(callee)状态被弹出,栈顶恢复到调用函数(caller

qq_40410406的博客 1万+

【AI智能体】Coze 搭建个人旅游规划助手实战详解

本文将详细介绍如何使用Coze平台搭建个人旅游规划助手。首先概述了AI智能体如何简化传统复杂任务的开发流程,然后重点介绍了Coze工作流的作用和核心节点类型(包括大模型、插件、知识库等)。通过实际操作演示,从创建智能体到配置多级工作流,逐步实现旅游规划功能:解析用户输入时间地点、查询必玩景点、获取景点详细信息等。该教程展示了如何利用Coze的可视化编排能力,即使非技术人员也能快速构建专业级AI应用。最终呈现的旅游助手可提供天气查询、行程建议等一站式服务。

Hello, New World! 2115

‌NTRU算法详细教程 | 2025年最新版(基于NIST后量子密码标准更新)

‌:NTRU是当前抗量子加密的黄金标准,‌。

blns_yxl的博客 1804

函数调用栈从何而来

程序员对函数调用栈是再熟悉不过了,无论是使用IDE调试还是GDB等工具进行调试,都离不开函数调用栈的分析。当我们遇到卡顿问题的时候,经常苦于没有卡顿现场,也就是函数调用栈进行分析解决。除了利用上述工具获取函数调用栈,能不能想办法在代码中记录函数调用栈,特别是卡顿的时候,还好是有办法的~

记录点滴,终成江河! 1213

RK3588部署rtmpose模型

摘要: 本文详细介绍了在RK3588开发板上部署RTMPose模型的全流程。首先在Ubuntu环境中搭建MMCV框架,通过MMPose工具将PTH模型转换为ONNX格式。随后使用RKNN-Toolkit2将ONNX模型转换为RKNN格式,并完成开发板部署。关键步骤包括模型转换(PTH→ONNX→RKNN)、环境配置和推理验证,最终实现人体姿态估计功能。整个过程涉及MMPose、RKNN-Toolkit等工具链的使用,为边缘计算场景下的实时姿态分析提供了可行方案。

qq_44224801的博客 1221

[C++]函数调用栈

函数调用时发生栈内存上的,这里主要涉及几个元素,函数调用,被调函数,函数参数。 涉及的过程主要有使用堆栈传递函数参数、保存返回地址、临时保存寄存器原有值(即函数调用的上下文)以备恢复以及存储本地局部变量。程序的内存可以参考进程内存 对于程序,编译器会对其分配一段内存,在逻辑上可以分为代码段,数据段,堆,栈 代码段:保存程序文本,指令指针EIP就是指向代码段,可读可执行不可写 数据段:保存初始

周大侠的专栏 2640

【保姆级教程/代码】GNSS反演大气可降水量(Precipitable Water Vapor, PWV)

GPS精密单点定位(PPP)是一种采用精密卫星星历和卫星钟差进行非差单点定位的方法,在观测过程中采用双频载波相位观测法以确保高精度定位精度。本文利用PPP技术来求解天顶对流层延迟(zenith tropospheric delay,ZTD)。ZTD由湿延迟(ZWD)和干延迟(ZHD)组成,其中占比90%的ZHD与地面测站高程、大气压和测站纬度等参数有良好的相关性,可以通过Saastamoinen模型精确求出;

weixin_43910227的博客 2927

c语言:读取文件中的指定内容

项目中要求从wifi的状态文件中提取出rssi字段的值,还有一个前提条件:必须与hwaddr(手机的MAC地址)一一对应。 wifi状态文件sta_info如下: # cat /proc/wlan0-vap0/sta_info -- STA info table -- (active: 1) 1: stat_info... state: 405 AuthAlgrthm: 0

u013485792的专栏 1万+

C语言函数调用栈(一)

程序的执行过程可看作连续的函数调用。当一个函数执行完毕时,程序要回到调用指令的下一条指令(紧接call指令)处继续执行。函数调用过程通常使用堆栈实现,每个用户态进程对应一个调用栈结构(call stack)。编译器使用堆栈传递函数参数、保存返回地址、临时保存寄存器原有值(即函数调用的上下文)以备恢复以及存储本地局部变量。 不同处理器和编译器的堆栈布局、函数调用方法都可能不同,但堆栈的基本概念是一...

——Light! 3万+

从零到一:在Ubuntu 20.04上搭建ROS1与PX4无人机开发环境

本文详细指导如何在Ubuntu 20.04系统上搭建完整的ROS1与PX4无人机开发环境。内容涵盖ROS Noetic安装、PX4固件源码编译、MAVROS通信桥接以及QGroundControl地面站的配置,并通过Gazebo仿真完成全链路联调测试,为无人机算法开发与验证提供稳定可靠的基础平台。

weixin_29292431的博客 167

函数调用栈 剖析+图解

栈: 在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。当发生函数调用的时候,栈空间中存放的数据是这样的:...

wangyin668的专栏 2万+

发那科机器人Modbus通讯配置全攻略:从IP设置到信号调试

本文详细介绍了发那科机器人Modbus通讯的配置方法,从基础认知到IP设置、端口配置、信号调试及故障排查。重点讲解了UOP和DI/DO信号的配置技巧,帮助工程师快速实现机器人与PLC的稳定通讯,提升自动化系统效率。

weixin_27872611的博客 623

编写一个期货跨期套利的程序,谈谈思路及案例

🏆本文收录于《优快云问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

**My Coding Family** 1719

栈、栈帧、函数调用约定

栈(Stack)的用途广泛,通常用于存储局部变量、传递函数参数、保存函数返回地址等。调试程序时需要不断查看栈内存,所以掌握栈的运行原理对于提升程序调试水平很有帮助。

weixin_43905689的博客 767

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

c语言函数调用栈

1.定义:栈(stack)又名堆栈是操作系统在建立某个进程时或者线程,为这个线程建立的存储区域,在编译的时候可以指定需要的栈的大小例如int a = 20;//在栈空间上开辟4字节如果存放变量太多就会造成栈溢出2.作用:编译器使用堆栈传递函数参数,保存返回地址、临时保存寄存器原有值(即函数调用的上下文)以备恢复以及存储本地局部变量。函数调用栈的实现与处理器寄存器组密切相关。3.寄存器的分配。

2403_87841499的博客 2029

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

c语言函数调用 压栈,局部变量与函数调用栈

不知道从什么时候开始,运行在OS内的程序文件,有了规范,Win系统下是PE,Linux系统下是ELF。符合规范的程序能够被OS调用并执行。不知道从什么时候开始,程序在OS的管控下执行,每个进程都有自己的堆(heap)和栈(stack)。堆的地址从小到大,存放需要程序代码显式申请的内存块,并且也需要程序自己管理和释放。栈的地址从大到小,存放函数调用过程中的指令地址和函数的局部变量。程序员需要关注堆的...

weixin_36155754的博客 1211
下一篇: 01.要疯了,到底什么是网络编程?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值