linux main函数汇编分析,Linux boot的第一步:启动汇编调用main函数

为了讲清原理,我们首先介绍C函数调用机制,然后再介绍汇编调用C函数。

一、C函数调用机制

对于汇编中的函数,其使用栈来传递参数和存储临时变量。其中的帧指针ebp用于定位参数和临时变量,而栈指针esp用于辅助所有的存储,包括ebp、各种返回跳转地址、参数和临时变量。

其示意图图如下:

dbb76c6ce8dc

栈帧结构

接下来我们对实例进行分析。

首先,给出C语言源码:

int add(int a, int b)

{

int c;

c=a+b;

return c;

}

int main()

{

int a, b, c;

a=1; b=2;

c=add(a, b);

return c;

}

进行汇编:

gcc -Wall -S -o test.s test.c

得到汇编源码:

.file "test.c"

.text

.globl add

.type add, @function

add:

pushl %ebp

movl %esp, %ebp

subl $16, %esp

movl 12(%ebp), %eax

movl 8(%ebp), %edx

leal (%edx,%eax), %eax

movl %eax, -4(%ebp)

movl -4(%ebp), %eax

leave

ret

.size add, .-add

.globl main

.type main, @function

main:

pushl %ebp

movl %esp, %ebp

subl $24, %esp

movl $1, -12(%ebp)

movl $2, -8(%ebp)

movl -8(%ebp), %eax

movl %eax, 4(%esp)

movl -12(%ebp), %eax

movl %eax, (%esp)

call add

movl %eax, -4(%ebp)

movl -4(%ebp), %eax

leave

ret

.size main, .-main

.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-18)"

.section .note.GNU-stack,"",@progbits

可以看到GCC现代版本会为局部变量多分配一些空间。main函数中分配了24个字节,其实12个就够了;add函数分配了16个字节,其实4个就够了。我对汇编源码修改为最少空间,发现也能运行。

其对应栈帧示意图如下:

dbb76c6ce8dc

add函数调用前后的栈帧结构

其中对应3个指令特别关键:

call:将返回指令压栈,并跳转到调用函数位置

ret:弹出栈顶处的地址,并跳转到其地址

leave:

movl %ebp, %esp

popl %ebp

二、汇编调用C函数

理解了C函数的调用机制,接下来就比较简单了。

对上面的例子可以进行分析。

首先,摘出汇编源码,1.s:

.text

.globl main

.type main, @function

main:

pushl %ebp

movl %esp, %ebp

subl $24, %esp

movl $1, -12(%ebp)

movl $2, -8(%ebp)

movl -8(%ebp), %eax

movl %eax, 4(%esp)

movl -12(%ebp), %eax

movl %eax, (%esp)

call add

movl %eax, -4(%ebp)

movl -4(%ebp), %eax

leave

ret

.size main, .-main

.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-18)"

.section .note.GNU-stack,"",@progbits

然后,对应的C函数,2.c:

int add(int a, int b)

{

int c;

c=a+b;

return c;

}

接下来使用gcc编译链接:

gcc -o test 1.s 2.c

这样,我们就知道Linux启动汇编是怎么调用main函数的,也就有了入门基础。

当然,还需要了解x86的保护模式,这个我推荐李忠老师的《x86汇编语言:从实模式到保护模式》。

码字快,画图耗时麻烦,希望大家认可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值