深入理解预编译,编译,汇编,链接的过程——之汇编
2015-12-10 10:48
274 查看
相比于编译,链接,汇编比预编译更少用。
汇编一个文件的过程如下。
范例1:LinuxFrame.c
int main(){
startkernel();
return 0;
}
汇编这个文件
$gcc -S LinuxFrame.c
生成LinuxFrame.s文件
.section
__TEXT,__text,regular,pure_instructions
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
.subsections_via_symbols
这个文件不容易看懂。
范例2 修改LinuxFrame.c,增加一个函数
void LoadBootCodeFromExDisk();
void startkernel(){
}
void LoadBootCodeFromExDisk(){
}
汇编
#gcc -S LinuxFrame.c
生成LinuxFrame.s如下
.section
__TEXT,__text,regular,pure_instructions
## @startkernel函数段
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
## @LoadBootCodeFromExDisk函数段
.globl
_LoadBootCodeFromExDisk
.align
4,
0x90
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp7:
.cfi_def_cfa_offset
16
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
.subsections_via_symbols
为了容易看懂,我增加了几个换行并增加了两行注释
## @startkernel函数段
## @LoadBootCodeFromExDisk函数段
我们容易看到:
.section
__TEXT,__text,regular,pure_instructions
这里是说这些语句放在text的段(.section __TEXT,__text),是普通的代码(regular),是纯指令(pure_instructions),这是我瞎猜的,如果猜错,请在下面留言告知。
startkernel函数段和LoadBootCodeFromExDisk函数段生成的语句几乎是一样的,除了startkernel和LoadBootCodeFromExDisk这两个标号。
这两个空函数生成的汇编指令由以下构成:
1
.globl
_LoadBootCodeFromExDisk
这句的意思是这里有一个全局可以调用的函数_LoadBootCodeFromExDisk,系统自动加上下划线_。
2
.align
4,
0x90
代码对齐方式,这是系统要求的。具体可以查阅align指令。对齐方式为4我看懂了,但是后面的0x90没看懂。
3
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
函数标号
4
.cfi_startproc
这好像是说,打开一个新的进程。
5
## BB#0:
pushq
%rbp
压栈寄存器
6
Ltmp7:
.cfi_def_cfa_offset
16
没看懂,好像是做一个什么偏移
7
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
没看懂,好像为rbp这些寄存器做一个什么偏移
8
Ltmp9:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
出栈,返回
9
.cfi_endproc
进程结束
范例3 LinuxFrame.c增加startkernel调用LoadBootCodeFromExDisk
void LoadBootCodeFromExDisk();
void startkernel(){
LoadBootCodeFromExDisk();
}
void LoadBootCodeFromExDisk()
{
}
汇编
$gcc -S LinuxFrame.c
生成LinuxFrame.s如下
.section
__TEXT,__text,regular,pure_instructions
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
callq
_LoadBootCodeFromExDisk
popq
%rbp
retq
.cfi_endproc
.globl
_LoadBootCodeFromExDisk
.align
4,
0x90
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp7:
.cfi_def_cfa_offset
16
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
.subsections_via_symbols
在Ltmp4:下面多增加了一行
callq
_LoadBootCodeFromExDisk
范例4:LinuxFrame.c打印输出
#include "stdio.h"
void LoadBootCodeFromExDisk();
void startkernel(){
LoadBootCodeFromExDisk();
}
void LoadBootCodeFromExDisk()
{
printf("abcdefg\n");
}
这个时候汇编输出,代码就多了很多,指令如上,我不再描述,输出的LinuxFrame.s如下:
.section
__TEXT,__text,regular,pure_instructions
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
callq
_LoadBootCodeFromExDisk
popq
%rbp
retq
.cfi_endproc
.globl
_LoadBootCodeFromExDisk
.align
4,
0x90
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp7:
.cfi_def_cfa_offset
16
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
subq
$16, %rsp
leaq
L_.str(%rip), %rdi
movb
$0, %al
callq
_printf
movl
%eax, -4(%rbp)
## 4-byte Spill
addq
$16, %rsp
popq
%rbp
retq
.cfi_endproc
.section
__TEXT,__cstring,cstring_literals
L_.str:
## @.str
.asciz
"abcdefg\n"
.subsections_via_symbols
在Ltmp9:下面多了以下代码:
subq
$16, %rsp
leaq
L_.str(%rip), %rdi
movb
$0, %al
callq
_printf
movl
%eax, -4(%rbp)
## 4-byte Spill
addq
$16, %rsp
另外还增加了一个新的段,这个段非指令段,而是数据段:
.section
__TEXT,__cstring,cstring_literals
L_.str:
## @.str
.asciz
"abcdefg\n"
这个段是一个字符串段(__cstring),里面有一个字符串“abcdefg\n",这个字符串有个标号L_.str:。
Ltmp9:下面新增的代码操作了寄存器,把字符串地址放到寄存器中,然后调用系统函数_printf,把这些文字显示在显示器上。
汇编一个文件的过程如下。
范例1:LinuxFrame.c
int main(){
startkernel();
return 0;
}
汇编这个文件
$gcc -S LinuxFrame.c
生成LinuxFrame.s文件
.section
__TEXT,__text,regular,pure_instructions
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
.subsections_via_symbols
这个文件不容易看懂。
范例2 修改LinuxFrame.c,增加一个函数
void LoadBootCodeFromExDisk();
void startkernel(){
}
void LoadBootCodeFromExDisk(){
}
汇编
#gcc -S LinuxFrame.c
生成LinuxFrame.s如下
.section
__TEXT,__text,regular,pure_instructions
## @startkernel函数段
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
## @LoadBootCodeFromExDisk函数段
.globl
_LoadBootCodeFromExDisk
.align
4,
0x90
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp7:
.cfi_def_cfa_offset
16
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
.subsections_via_symbols
为了容易看懂,我增加了几个换行并增加了两行注释
## @startkernel函数段
## @LoadBootCodeFromExDisk函数段
我们容易看到:
.section
__TEXT,__text,regular,pure_instructions
这里是说这些语句放在text的段(.section __TEXT,__text),是普通的代码(regular),是纯指令(pure_instructions),这是我瞎猜的,如果猜错,请在下面留言告知。
startkernel函数段和LoadBootCodeFromExDisk函数段生成的语句几乎是一样的,除了startkernel和LoadBootCodeFromExDisk这两个标号。
这两个空函数生成的汇编指令由以下构成:
1
.globl
_LoadBootCodeFromExDisk
这句的意思是这里有一个全局可以调用的函数_LoadBootCodeFromExDisk,系统自动加上下划线_。
2
.align
4,
0x90
代码对齐方式,这是系统要求的。具体可以查阅align指令。对齐方式为4我看懂了,但是后面的0x90没看懂。
3
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
函数标号
4
.cfi_startproc
这好像是说,打开一个新的进程。
5
## BB#0:
pushq
%rbp
压栈寄存器
6
Ltmp7:
.cfi_def_cfa_offset
16
没看懂,好像是做一个什么偏移
7
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
没看懂,好像为rbp这些寄存器做一个什么偏移
8
Ltmp9:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
出栈,返回
9
.cfi_endproc
进程结束
范例3 LinuxFrame.c增加startkernel调用LoadBootCodeFromExDisk
void LoadBootCodeFromExDisk();
void startkernel(){
LoadBootCodeFromExDisk();
}
void LoadBootCodeFromExDisk()
{
}
汇编
$gcc -S LinuxFrame.c
生成LinuxFrame.s如下
.section
__TEXT,__text,regular,pure_instructions
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
callq
_LoadBootCodeFromExDisk
popq
%rbp
retq
.cfi_endproc
.globl
_LoadBootCodeFromExDisk
.align
4,
0x90
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp7:
.cfi_def_cfa_offset
16
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
popq
%rbp
retq
.cfi_endproc
.subsections_via_symbols
在Ltmp4:下面多增加了一行
callq
_LoadBootCodeFromExDisk
范例4:LinuxFrame.c打印输出
#include "stdio.h"
void LoadBootCodeFromExDisk();
void startkernel(){
LoadBootCodeFromExDisk();
}
void LoadBootCodeFromExDisk()
{
printf("abcdefg\n");
}
这个时候汇编输出,代码就多了很多,指令如上,我不再描述,输出的LinuxFrame.s如下:
.section
__TEXT,__text,regular,pure_instructions
.globl
_startkernel
.align
4,
0x90
_startkernel:
## @startkernel
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp2:
.cfi_def_cfa_offset
16
Ltmp3:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
callq
_LoadBootCodeFromExDisk
popq
%rbp
retq
.cfi_endproc
.globl
_LoadBootCodeFromExDisk
.align
4,
0x90
_LoadBootCodeFromExDisk:
## @LoadBootCodeFromExDisk
.cfi_startproc
## BB#0:
pushq
%rbp
Ltmp7:
.cfi_def_cfa_offset
16
Ltmp8:
.cfi_offset %rbp,
-16
movq
%rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
subq
$16, %rsp
leaq
L_.str(%rip), %rdi
movb
$0, %al
callq
_printf
movl
%eax, -4(%rbp)
## 4-byte Spill
addq
$16, %rsp
popq
%rbp
retq
.cfi_endproc
.section
__TEXT,__cstring,cstring_literals
L_.str:
## @.str
.asciz
"abcdefg\n"
.subsections_via_symbols
在Ltmp9:下面多了以下代码:
subq
$16, %rsp
leaq
L_.str(%rip), %rdi
movb
$0, %al
callq
_printf
movl
%eax, -4(%rbp)
## 4-byte Spill
addq
$16, %rsp
另外还增加了一个新的段,这个段非指令段,而是数据段:
.section
__TEXT,__cstring,cstring_literals
L_.str:
## @.str
.asciz
"abcdefg\n"
这个段是一个字符串段(__cstring),里面有一个字符串“abcdefg\n",这个字符串有个标号L_.str:。
Ltmp9:下面新增的代码操作了寄存器,把字符串地址放到寄存器中,然后调用系统函数_printf,把这些文字显示在显示器上。
相关文章推荐
- nodejs 基础问题
- NSURLSessionDownloadTask 出现 NSURLErrorDomain的解决方案
- Android 常用工具类
- 来玩Play框架01 简介
- 12.10 android双向通话录音,ClipData监听,coding.net pymongo连接使用mongo
- 给Android Studio导入第三方库的方法
- 如何进行oracle capability i/o(压力测试数据库服务器i/o性能)
- UESTC 250 windy数 数位dp
- HTML DOM 方法
- linux ubuntu解压tar.gz安装mysql
- 5 Ways of Creating a Stream in Java 8
- 最小二乘法及其应用
- HTML DOM 节点
- android中延迟执行某个任务
- LeetCode:Search Insert Position
- javascript的简单发展过程(简到不能再简了)
- HashMap与TreeMap的区别
- URi和Url格式
- Python常用内建模块
- 从反思谈论阵列和指针的几个问题,腾讯的笔名