首页 > 其他分享 >20240819编译 链接 单片机执行的第一个语句

20240819编译 链接 单片机执行的第一个语句

时间:2024-08-22 23:03:57浏览次数:11  
标签:语句 文件 函数 start 单片机 say main 链接 20240819

2024年8月中旬在宝鸡出差,在B站上学习了下。

在linux操作系统中,gdb是调试器,gcc是编译器。

Linux 操作系统 将main.elf文件加载到内存中以后,操作系统为其分配进程,然后main函数就开始执行了。

输入 layout asm 则显示出来汇编代码 

键入 “starti”的时候 

进入到程序里面的第一个指令执行  发现程序进入的第一个指令 并不是main函数 而且是一个在库文件 Lib64/ld-linux-x86-64.so.2

这个start的地址是 0x7ffff7fe32b0 并不是mian 的首地址。 

然后在strat上再次打断点 

然后又进入了一个start里面

这个start 的地址是 0X555555555060  应该是程序自己的一个statrt 还没有进入到main 

然后在Main上打断点  。

 

用”ni”指令继续执行程序,程序调用了一个_GI_exit 实际上这个指令就是操作系统帮我们结束进程。 

20240818学习

进行预处理

 

进行编译成汇编 

 

可以看见下图 在Data 段落定义了字符传 hellow word   定义了main符号 是在代码段main 符号里面 都是X86汇编代码。

还发现: 

 

然后我还发现了作者是不是在 B站上写文章呢,也象知乎那样?

后来我发现是在博客园写的,写的比较好看

地址:编译?汇编?链接? - yudoge - 博客园 (cnblogs.com)

 

 

例如我们刚才看到的prinf 函数的调用 实际上CALL指令后面还是符号  目前不知道去哪里找这个 puts@PLT 这个东西 

 

实际上,打开预处理的源文件后 看见printf 也就是一个外部函数的申明,也没有函数体 

 

综上:所以单靠main一个文件是无法编译连接出可执行文件程序的。 还需要将printf在最后的可执行文件里面找到。

 

下一步:汇编main.s 通过编译编译变为可重定向的目标文件 main.o

可用 gcc命令做这个事情 

Gcc-c main.c  -o gcc main.o 

通过vim指令 可以看下 main.o 其实也看不了  因为已经是一个二进制文件 

 

但是可以使用 objdump 命令看下里面的代码信息 

 

 

通过上图可以看见 编译以后 Main函数还没有分配地址, 

 

 

 

通过上图 可以看见 e8 应该是call  call 后面也要跟地址,但是目前地址也是00 00 00 00

也不知从哪里去调用这个printf

 

我们可以通过-t 来看下符号表 如下图 

 

展开后的符号表 如下图所示 

 

通过下图可以看见 puts 符号是未定义的 

 

 

现在对目标文件进行链接的话, 可执行文件是执行不了的。

用 test  Ld main .o  - o main  发现如下图

如下图 提示有一个未定义的引用。 “puts”

那么符号“puts” 可能存在于另外一个目标文件.obj中,需要将另外一个目标文件也链接进来。 于是下一步 将两个目标文件obj ,链接到一个目标文件里面。 

2024年8月18日晚上

例如现在定义了两个C源文件  a.c 和 say.c

 

注意a.c文件中main()函数之前并没有包括头文件 #include“stdio.h“  于是在下面的图10中 会提示找不到 start 符号标识。 提示了警告 cannot find entry symbol _start; default   0x0000401000

 

a.c

Say.c

Void say()

Int main()

{

  Say();

}

Void say()

{

   int a = 10 ;

   while(1);

}

 

 

希望a.c文件中调用say()函数 

用gcc-c命令 生成目标文件

Gcc-c   a.c   -o   a.o

Gcc-c   say.c   -o  say.o

通过 objdump  -d   -t  a.o 来查看a.o 的目标链接文件。 如下图 

 

 

 

a.o 的目标链接文件如下图   实际下图的call函数 调用的是ssay函数 显然因为say函数没有在a.c函数中定义,所以 显示say函数是 UND   undefine 没有定义。

 

 

 

但是 say.o 中有这say这个符号的。 

 

 

 

于是可以把a.o 和 say.o 链接在仪器  输出一个a.out  

 

 

 

但是提示了 cannot find entry symbol _start; default   0x0000401000

因为:注意到a.c文件中main()函数之前并没有包括头文件 #include“stdio.h“  于是在下面的图10中 会提示找不到 start 符号标识。 提示了警告 cannot find entry symbol _start; default   0x0000401000   

 

通过以下命令 强制的指定main () 函数 作为入口地址  

Ld  -e main  a.o say.o  -o   a.out  “e” 表示的是entry  即入口地址 

 

 

 

通过上图中的  objdump  -d -t a.out   可以查看a.out 中的符号表 如下图 

 

 

 

 

 

可以看到 main 函数 和 say 函数的入口地址均已经指定了。 

 

然后 也看见 符号表 里面也没有  出现 UNDEF 地址了。 

 

 

 

于是 明白了链接的意义了, 即 不同文件里面的 可执行文件 .obj 合格成一个 可执行文件,把没有定义的符号,也定义了。

 

接下来我们回到问题, 操作系统执行的main 函数,操作系统结束了main 函数  

 

2024年8月22日先总结到这里

百度网盘链接 

我的网盘  博客园上的文章  20240817_用gdb调试器调试main找进入main 之前的函数.rar

 

标签:语句,文件,函数,start,单片机,say,main,链接,20240819
From: https://www.cnblogs.com/bailongwei654321/p/18374924

相关文章

  • 织梦dedecms使用sql语句获取文章链接地址
    在织梦DeDeCMS中,可以通过SQL语句结合织梦特有的标签来获取文章链接地址。以下是如何使用SQL语句获取文章链接地址的具体步骤和示例。1.SQL语句织梦CMS允许在模板中使用自定义SQL语句来获取数据。这可以通过 {dede:sql} 标签来实现。2.获取文章链接地址SQL语句:编写SQL语句......
  • C语言的语句分类
    C语言的代码是由一条条语句构成的,可分为五类:空语句一个分号就是一个语句,即空语句,一般出现的地方是:这里需要一条语句,但这个语句不需要做任何事。表达式语句在表达式的后面加上分号,构成表达式语句。函数调用语句复合语句成对括号中的代码构成一个代码块,也称复合语句。控......
  • 从零开始学习C++之if判断语句
    当你想判断某个条件时,怎么办呢?当当当当(日常发疯),if语句就派上用场了。使用方法不多废话,使用格式如下:if(条件){ 代码}elseif(条件){ 代码}else{ 代码}注:elseif/else可以没有。这几个条件中只能满足一个。例:if(n==1){ cout<<1;}elseif(n==1)......
  • [Mysql]执行一条语句的过程
    执行一条select语句,期间发生了什么?学习SQL的时候,大家肯定第一个先学到的就是select查询语句了,比如下面这句查询语句://在product表中,查询id=1的记录select*fromproductwhereid=1;但是有没有想过,MySQL执行一条select查询语句,在MySQL中期间发生了什么?......
  • MySql中常用的sql语句大全(工作常用篇)
    1.DDL1.1操作数据库--创建库createdatabase库名;--创建库时判断库是否存在,不存在则创建createdatabaseifnoexists库名;--查看所有数据库showdatabases;--使用指定数据库use库名;--查看当前指定数据库包含的数据表showtables;--查看数据库的结......
  • oracle 如果是多条插入语句用begin end 快还是一条一条插入快?
    在Oracle数据库中,对于多条插入语句,使用BEGIN...END块(结合事务控制)通常会比一条一条地插入更快,尤其是在处理大量数据时。这主要是因为以下几个原因:减少网络往返次数:当在应用程序和数据库之间执行SQL语句时,每条SQL语句的发送和执行都需要网络往返时间。将多条插入语句封装在B......
  • try...except 语句通常用于捕获和处理可能在代码执行过程中发生的异常
    在Django中,try...except语句通常用于捕获和处理可能在代码执行过程中发生的异常。这有助于防止程序因未处理的错误而崩溃,并允许开发者优雅地处理错误场景。以下是一些常见的用法示例:1.数据库操作中的异常处理在进行数据库操作时,可能会遇到如数据不存在、唯一性约束违反等问题......
  • 【教学类-72-02】20240819建筑对称图纸02(图案最大化)
    背景需求【教学类-72-01】20240803建筑对称图纸01-CSDN博客文章浏览阅读423次,点赞13次,收藏5次。【教学类-72-01】20240803建筑对称图纸01https://blog.csdn.net/reasonsummer/article/details/140893003我感觉房子有大有小,有大量空白,我想让建筑变得最大使用以下代码,把房子......
  • Spring Mybatis拦截器配合logback打印完整sql语句
    在项目开发与维护过程中,常常需要对程序执行的sql语句,进行观察和分析。但是项目通常默认会使用org.apache.ibatis.logging.stdout.StdOutImpl日志配置,该配置是用System.out.println打印的日志,导致只能将执行语句打印到控制台,却没办法打印到日志文件中。如果放开logback日志等......
  • mysql 语句的执行顺序
    MySQL语句的执行顺序如下:FROM 子句:确定数据来源的表或表达式。ON 子句:应用 JOIN 条件,如果有的话。JOIN 子句:如果有的话,根据 JOIN 类型(如 INNERJOIN, LEFTJOIN 等)连接表。WHERE 子句:过滤记录,只留下满足条件的记录。GROUPBY 子句:根据指定的......