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

 

posted @ 2024-08-22 23:06  STEVEN-SUN  阅读(10)  评论(0编辑  收藏  举报