您的位置:首页 > 其它

深入理解预编译,编译,汇编,链接的过程——之汇编

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,把这些文字显示在显示器上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: