> 计算机的指令分类:
伪指令:机器指令序列
机器指令:机器指令和汇编指令一一对应
汇编指令:机器指令的汇编语言
微指令:微程序级指令,属于硬件范畴,这点组成原理上有讲过。
其中汇编指令和机器指令都属于机器级指令。
启发:
汇编在转换为机器指令时并没有进行优化,相同的汇编程序在执行时带来的效率差 别应该源于硬件的不同。
ISA(指令级体系结构)的存在使得汇编更方便移植。
在此可见ISA在整个计算机系统抽象层中的重要性。
> 生成机器代码的过程:
用 GCC + Linux + IA32 平台进行实验
程序转换四个步骤:
1. 预处理
引入#include<文件>和处理宏语句
2. 编译
将处理后的源程序文件编译成相应的汇编语言程序。
3. 汇编
将汇编源程序文件转换为可重定位的机器语言目标代码文件。
4. 链接
由连接器将多个可重定位的机机器语言目标程序文件以及库例程连接起来,得到可执行文件。
> 这里以hello.cpp为例
-第一步
> gcc -E hello.cpp -o hello.i
因为引入了<iostream>输入输出流文件,所以.......预处理后特别长
hello.i 大小:411KB
注意到了吗?在这里我用gcc对c++源文件进行预处理居然也是可以的。
好奇提问:GCC 对于 c 和 cpp 的预处理操作是相同的吗? gcc -E
加一条指令:g++ -E hello.cpp -o hello++.i
从实验结果上:
GCC 对于cpp的预处理跟G++效果相同。但后续就完全不同了。
-第二步
> g++ -S hello.i -o hello.s
得到的汇编指令有80行
hello.s 大小:2KB
-第三步
> g++ -c hello.s -o hello.o
目标程序 hello.o 有3KB (这里只生成了一个目标文件)
-第四步
> g++ hello.o -o hello
执行程序大小: 9KB
-执行吧少年!!
./hello
Hola!
------正文完------
附录:
g++ manual 摘录:
-E Stop after the preprocessing stage; do not run the compiler
proper. The output is in the form of preprocessed source code,
which is sent to the standard output.
Input files that don‘t require preprocessing are ignored.
-c Compile or assemble the source files, but do not link. The
linking stage simply is not done. The ultimate output is in the
form of an object file for each source file.
By default, the object file name for a source file is made by
replacing the suffix .c, .i, .s, etc., with .o.
Unrecognized input files, not requiring compilation or assembly,
are ignored.
-S Stop after the stage of compilation proper; do not assemble. The
output is in the form of an assembler code file for each non-
assembler input file specified.
By default, the assembler file name for a source file is made by
replacing the suffix .c, .i, etc., with .s.
Input files that don‘t require compilation are ignored.
-o file
Place output in file file. This applies to whatever sort of
output is being produced, whether it be an executable file, an
object file, an assembler file or preprocessed C code.
If -o is not specified, the default is to put an executable file
in a.out, the object file for source.suffix in source.o, its
assembler file in source.s, a precompiled header file in
source.suffix.gch, and all preprocessed C source on standard
output.
更多关于gcc/g++的使用请自行查询
hello.cpp 源文件
# include<iostream>
using namespace std;
int main()
{
cout<<"Hola!"
}
(正向编译)汇编指令源程序(AT&T格式):
.file "hello.cpp" .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .section .rodata .LC0: .string "Hola!" .text .globl main .type main, @function main: .LFB971: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %esi movl $_ZSt4cout, %edi call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE971: .size main, .-main .type _Z41__static_initialization_and_destruction_0ii, @function _Z41__static_initialization_and_destruction_0ii: .LFB975: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl %edi, -4(%rbp) movl %esi, -8(%rbp) cmpl $1, -4(%rbp) jne .L3 cmpl $65535, -8(%rbp) jne .L3 movl $_ZStL8__ioinit, %edi call _ZNSt8ios_base4InitC1Ev movl $__dso_handle, %edx movl $_ZStL8__ioinit, %esi movl $_ZNSt8ios_base4InitD1Ev, %edi call __cxa_atexit .L3: leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE975: .size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii .type _GLOBAL__sub_I_main, @function _GLOBAL__sub_I_main: .LFB976: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $65535, %esi movl $1, %edi call _Z41__static_initialization_and_destruction_0ii popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE976: .size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main .section .init_array,"aw" .align 8 .quad _GLOBAL__sub_I_main .hidden __dso_handle .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" .section .note.GNU-stack,"",@progbits
有道云笔记粘贴过来格式丢了个八九不离十
转载请注明出处 :)