qemu-basics - プログラムのコンパイルプロセス (4)

プログラムのコンパイル プロセス

コンピュータプログラミング言語は通常、機械語、アセンブリ言語、高級言語の 3 つのカテゴリに分類されます。高級言語は機械語に翻訳して実行する必要があり、コンパイルする方法と解釈する方法の2つの翻訳方法があるため、基本的に高級言語を2つのカテゴリーに分け、一方はコンパイルするC、C++、Java などの型言語と、Python、Ruby、MATLAB、JavaScript などのインタープリター型言語です。

ここでは、高級 C/C++ 言語で記述されたプログラムを、プロセッサが実行できるバイナリ コードに変換する方法を紹介します。次の 4 つの手順が含まれます。

  • 前処理 (前処理、プリプロセッサ cpp、役割: .c/s -> .i
  • コンパイル、アセンブラ ccl、関数: .i -> .s
  • コンパイル (アセンブリ)、コンパイラ as、関数: .s -> .o
  • リンク、リンカー ld、役割: .o -> elf 実行ファイル

声明

コンテンツの一部は、侵入して削除されたインターネットから取得されます。

GCC 共通ツールチェーン

一般に GCC と呼ばれるのは、Linux システムで一般的に使用されるコンパイル ツールである GUN Compiler Collection の略語です。GCC ツール チェーン ソフトウェアには、GCC、Binutils、C ランタイム ライブラリなどが含まれます。

GCC

GCC (GNU C コンパイラ) はコンパイル ツールです。C/C++言語で書かれたプログラムをプロセッサが実行できるバイナリコードに変換する処理は、コンパイラによって完了します。

Binutils

addr2line、ar、objcopy、objdump、as、ld、ldd、readelf、size などのバイナリ プログラム処理ツールのセット。この一連のツールは、開発とデバッグに不可欠なツールであり、その簡単な紹介は次のとおりです。

  • addr2line: プログラムアドレスを対応するプログラムソースファイルと対応するコード行に変換し、対応する関数を取得するために使用されます。このツールは、デバッガーがデバッグ中に対応するソース コードの場所を見つけるのに役立ちます。
  • as: 主に組み立てに使用します。組み立ての詳細な紹介は以下を参照してください。
  • ld: 主にリンクのために使用されます. リンクの詳細については, 以下のテキストを参照してください.
  • ar: 主に静的ライブラリの作成に使用されます。初心者の理解を容易にするために、動的ライブラリと静的ライブラリの概念をここで紹介します。
    • 複数の .o オブジェクト ファイルをライブラリ ファイルに生成する場合、ライブラリには静的ライブラリと動的ライブラリの 2 種類があります。
      Windows では、スタティック ライブラリは拡張子が .lib のファイルで、共有ライブラリは拡張子が .dll のファイルです。Linux では、スタティック ライブラリは接尾辞 .a が付いたファイルであり、共有ライブラリは接尾辞 .so が付いたファイルです。
    • 静的ライブラリと動的ライブラリの違いは、コードがロードされる瞬間が異なることです。スタティック ライブラリのコードは、コンパイル プロセス中に実行可能プログラムに読み込まれているため、サイズは比較的大きくなります。共有ライブラリのコードは、実行プログラムの実行時にメモリにロードされ、コンパイル プロセス中に参照されるだけなので、コード サイズは小さくなります。Linux システムでは、ldd コマンドを使用して、実行可能プログラムが依存する共有ライブラリーを表示できます。
      システムで同時に実行する必要がある複数のプログラムがあり、これらのプログラム間に共有ライブラリがある場合、動的ライブラリを使用するとメモリをさらに節約できます。
  • ldd: 実行可能プログラムが依存する共有ライブラリを表示するために使用できます。
  • objcopy: .bin を .elf に変換したり、.elf を .bin に変換したりするなど、1 つのオブジェクト ファイルを別の形式に変換します。
  • objdump: 主な機能は逆アセンブルです。逆アセンブルの詳細については、次のテキストを参照してください。
  • readelf: ELF ファイルに関する情報を表示します。詳細については、以下を参照してください。
  • size: 実行ファイル、コードセグメント、データセグメント、合計サイズなどの各部分のサイズと合計サイズをリストします。size を使用した具体的な使用例については、以下を参照してください。

C ランタイム ライブラリ

C 言語標準は、主に 2 つの部分で構成されています。1 つは C の構文を記述し、もう 1 つは C 標準ライブラリを記述しています。C 標準ライブラリは一連の標準ヘッダー ファイルを定義し, 各ヘッダー ファイルには関連する関数, 変数, 型宣言およびマクロ定義が含まれています. たとえば, 一般的な printf 関数は C 標準ライブラリ関数であり, そのプロトタイプはstdio ヘッダー ファイル。

C 言語標準は、C 標準ライブラリ関数のプロトタイプを定義するだけで、実装は提供しません。したがって、C 言語コンパイラーは通常、C ランタイム・ライブラリー (C ランタイム・ライブラリー、CRT) のサポートを必要とします。C ランタイム ライブラリは、単に C ランタイム ライブラリと呼ばれることがよくあります。C 言語と同様に、C++ も独自の標準を定義し、C++ ランタイム ライブラリと呼ばれる関連するサポート ライブラリを提供します。

ENV

GCC ツール チェーンは主に Linux 環境で使用されるため、この記事でも Linux システムを作業環境として使用します。コンパイルの全プロセスを示すために、このセクションではまず例として C 言語で記述された単純な Hello プログラムを用意します。そのソース コードは次のとおりです。

#include<stdio.h>

int main(int argc, char *argv[])
{
    
    
    printf("hello world\r\n");

    return 0;
}

コンパイルプロセス

前処理

前処理プロセスには、主に次のプロセスが含まれます。

  • すべての #define を削除し、すべてのマクロ定義を展開し、#if #ifdef #elif #else #endif などのすべての条件付きプリコンパイル済みディレクティブを処理します。
  • #include プリコンパイル済みディレクティブを処理し、インクルード ファイルをプリコンパイル済みディレクティブの場所に挿入します。
  • コメント「//」と「/* */」をすべて削除します。
  • 行番号とファイル識別子を追加して、コンパイル時にデバッグ行番号とコンパイル エラー警告行番号を生成します。
  • 後続のコンパイル パスに必要なすべての #pragma コンパイラ ディレクティブを保持します。

gcc で前処理するコマンドは次のとおりです。

gcc -E test.c -o test.i

GCC オプション -E により、前処理後に GCC が停止する

上記のコマンドは、ソースファイル test.c を前処理して test.i を生成するものです. test.i ファイルの内容は次のとおりです.

extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 885 "/usr/include/stdio.h" 3 4
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 902 "/usr/include/stdio.h" 3 4

# 2 "test.c" 2


# 3 "test.c"
int main(int argc, char *argv[])
{
    
    
    printf("hello world\r\n");

    return 0;
}

test.i ファイルを開いて、通常のテキスト ファイルとして表示できます。

コンパイル

コンパイル プロセスでは、前処理されたファイルに対して一連の字句解析、構文解析、意味解析、および最適化を実行して、対応するアセンブリ コードを生成します。

gccでコンパイルするコマンドは以下の通り

gcc -S test.i -o test.s

GCC のオプション -S により、コンパイル後に GCC が停止し、アセンブラーが生成される

上記のコマンドは、生成された test.i ファイルを前処理して、アセンブラー test.s をコンパイルおよび生成します。

コンパイル

アセンブリ プロシージャ コールは、アセンブリ コードを処理し、プロセッサが認識できる命令を生成して、オブジェクト ファイルにサフィックス .o を付けて保存します。各アセンブリステートメントはほぼプロセッサ命令に対応しているため、アセンブリプロセスは、アセンブリ命令とプロセッサ命令の比較表に従って、Binutils のようにアセンブラを呼び出すことで、コンパイルプロセスよりも簡単です。

プログラムが複数のソースコードファイルで構成されている場合、各ファイルはまずアセンブリ作業を完了する必要があり、次のリンク作業に入る前に .o オブジェクト ファイルが生成されます。注: オブジェクト ファイルは既に最終的なプログラムの一部ですが、リンクされるまで実行できません。

gccを使ってアセンブルするコマンドは以下の通り

 gcc -c test.s -o test.o

GCC オプション -c により、アセンブリの実行後に GCC が停止し、オブジェクト ファイルが生成されます。

またはアセンブリについては直接呼び出します

as -c hello.s -o hello.o

Binutils の as を使用して、hello.s ファイルをアセンブルし、オブジェクト ファイルを生成します。

注: test.o オブジェクト ファイルは、ELF (Executable and Linkable Format) 形式のリダイレクト可能なファイルです。

リンク

リンクも静的リンクと動的リンクに分けられますが、主なポイントは次のとおりです。

  • 静的リンクとは、コンパイル フェーズ中に静的ライブラリを実行可能ファイルに直接追加することを指します。そのため、実行可能ファイルは比較的大きくなります。リンカーは、関数のコードをその場所 (別のオブジェクト ファイルまたは静的にリンクされたライブラリ内) から最終的な実行可能プログラムにコピーします。実行可能ファイルを作成するためにリンカーが完了する必要がある主なタスクは、シンボルの解決 (オブジェクト ファイル内のシンボルの定義と参照を関連付ける) と再配置 (シンボル定義をメモリ アドレスに対応させ、すべての参照を変更する) です。記号に )。
  • 動的リンクとは、リンク段階で一部の記述情報のみが追加され、プログラムの実行時に対応する動的ライブラリがシステムからメモリにロードされることを意味します。
    • Linuxシステムでは、通常、gccがコンパイルおよびリンクする際の動的ライブラリの検索パスの順序は、最初にgccコマンドのパラメータ-Lで指定されたパスから検索し、次に環境変数LIBRARY_PATHで指定されたパスからアドレスを検索し、その後、デフォルトのパスから検索して /lib、/usr/lib、/usr/local/lib を探します。
    • Linux システムでは、通常、バイナリ ファイルを実行する際の動的ライブラリの検索パスの順序は、まずオブジェクト コードのコンパイル時に指定された動的ライブラリの検索パスを検索し、次に環境変数 LD_LIBRARY_PATH で指定されたパスからアドレスを検索し、次にコンフィギュレーションからアドレス指定します。 file /etc/ ld.so.conf で指定された動的ライブラリ検索パス; 次に、デフォルト パス /lib、/usr/lib から検索します。
    • Linux システムでは、ldd コマンドを使用して、実行可能プログラムが依存する共有ライブラリーを表示できます。
  • 動的ライブラリと静的ライブラリをリンクするためのパスは重複する可能性があるため、libtest.a と libtest.so のように静的ライブラリ ファイルと動的ライブラリ ファイルが同じ名前でパスに存在する場合、gcc はデフォルトで動的ライブラリを優先します。リンク時に libtest.so をリンクします。gcc に libtest.a のリンクを選択させたい場合は、gcc オプション - static を指定できます。これにより、リンクに静的ライブラリの使用が強制されます。例として、Hello World を取り上げます。
    • コマンド「gcc hello.c -o hello」を使用すると、動的ライブラリがリンクに使用されます. 生成された ELF 実行ファイルのサイズ (Binutils の size コマンドを使用して表示) およびリンクされた動的ライブラリ (表示する Binutils の ldd コマンド) は次のとおりです。
      gcc test.c -o test
      
      size test
          text    data     bss     dec     hex filename
          1386     600       8    1994     7ca test
      
      ldd test
          linux-vdso.so.1 (0x00007fffb99f4000)
          libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc2a3600000)
          /lib64/ld-linux-x86-64.so.2 (0x00007fc2a39a9000)
      
    • コマンド「gcc -static hello.c -o hello」を使用すると、スタティック ライブラリがリンクに使用され、生成された ELF 実行可能ファイルのサイズ (Binutils の size コマンドを使用して表示) およびリンクされたダイナミック ライブラリ ( Binutils の ldd コマンドを使用して、次のように表示します。
      gcc -static test.c -o test
      
      size test
          text    data     bss     dec     hex filename
          781877   23240   23016  828133   ca2e5 test
      ldd test
          not a dynamic executable
      
    • 上記の結果から、動的にリンクされたファイルは小さく、静的にリンクされたファイルは大きいことがわかります。

リンカーによって生成される最終的なファイルは、ELF 形式の実行可能ファイルです. ELF 実行可能ファイルは、通常、.text、.data、.rodata、.bss などのさまざまなセグメントにリンクされます。

ELF ファイルを分析する

ELF ファイルのセクション

ELF ファイルの形式は次のとおりです。ELF ヘッダーとセクション ヘッダー テーブルの間のセクションがセクションです。

ELF header
Program header table
.text
.rodata
...
.data
Section header table

一般的な ELF ファイルには次のセクションが含まれます

  • .text: コンパイルされたプログラムの命令コード セグメント。
  • .rodata: ro は読み取り専用、つまり読み取り専用データ (定数 const など) を表します。
  • .data: 初期化された C プログラムのグローバル変数と静的ローカル変数。
  • .bss: 初期化されていない C プログラムのグローバル変数と静的ローカル変数。
  • .debug: デバッグ シンボル テーブル。デバッガーはこのセクションの情報を使用してデバッグを支援します (コンパイル時に -g オプションを追加する必要があります)。

readelf -S を使用して、各セクションの情報を表示できます

readelf -S test

上記のコマンドで表示される詳細情報は次のとおりです。

There are 31 section headers, starting at offset 0x3698:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [1] .interp           PROGBITS         0000000000000318  00000318
       000000000000001c  0000000000000000   A       0     0     1
  [2] .note.gnu.pr[...] NOTE             0000000000000338  00000338
       0000000000000030  0000000000000000   A       0     0     8
  [3] .note.gnu.bu[...] NOTE             0000000000000368  00000368
       0000000000000024  0000000000000000   A       0     0     4
  [4] .note.ABI-tag     NOTE             000000000000038c  0000038c
       0000000000000020  0000000000000000   A       0     0     4
  [5] .gnu.hash         GNU_HASH         00000000000003b0  000003b0
       0000000000000024  0000000000000000   A       6     0     8
  [6] .dynsym           DYNSYM           00000000000003d8  000003d8
       00000000000000a8  0000000000000018   A       7     1     8
  [7] .dynstr           STRTAB           0000000000000480  00000480
       000000000000008d  0000000000000000   A       0     0     1
  [8] .gnu.version      VERSYM           000000000000050e  0000050e
       000000000000000e  0000000000000002   A       6     0     2
  [9] .gnu.version_r    VERNEED          0000000000000520  00000520
       0000000000000030  0000000000000000   A       7     1     8
  [10] .rela.dyn         RELA             0000000000000550  00000550
       00000000000000c0  0000000000000018   A       6     0     8
  [11] .rela.plt         RELA             0000000000000610  00000610
       0000000000000018  0000000000000018  AI       6    24     8
  [12] .init             PROGBITS         0000000000001000  00001000
       000000000000001b  0000000000000000  AX       0     0     4
  [13] .plt              PROGBITS         0000000000001020  00001020
       0000000000000020  0000000000000010  AX       0     0     16
  [14] .plt.got          PROGBITS         0000000000001040  00001040
       0000000000000010  0000000000000010  AX       0     0     16
  [15] .plt.sec          PROGBITS         0000000000001050  00001050
       0000000000000010  0000000000000010  AX       0     0     16
  [16] .text             PROGBITS         0000000000001060  00001060
       0000000000000112  0000000000000000  AX       0     0     16
  [17] .fini             PROGBITS         0000000000001174  00001174
       000000000000000d  0000000000000000  AX       0     0     4
  [18] .rodata           PROGBITS         0000000000002000  00002000
       0000000000000011  0000000000000000   A       0     0     4
  [19] .eh_frame_hdr     PROGBITS         0000000000002014  00002014
       0000000000000034  0000000000000000   A       0     0     4
  [20] .eh_frame         PROGBITS         0000000000002048  00002048
       00000000000000ac  0000000000000000   A       0     0     8
  [21] .init_array       INIT_ARRAY       0000000000003db8  00002db8
       0000000000000008  0000000000000008  WA       0     0     8
  [22] .fini_array       FINI_ARRAY       0000000000003dc0  00002dc0
       0000000000000008  0000000000000008  WA       0     0     8
  [23] .dynamic          DYNAMIC          0000000000003dc8  00002dc8
       00000000000001f0  0000000000000010  WA       7     0     8
  [24] .got              PROGBITS         0000000000003fb8  00002fb8
       0000000000000048  0000000000000008  WA       0     0     8
  [25] .data             PROGBITS         0000000000004000  00003000
       0000000000000010  0000000000000000  WA       0     0     8
  [26] .bss              NOBITS           0000000000004010  00003010
       0000000000000008  0000000000000000  WA       0     0     1
  [27] .comment          PROGBITS         0000000000000000  00003010
       000000000000002b  0000000000000001  MS       0     0     1
  [28] .symtab           SYMTAB           0000000000000000  00003040
       0000000000000360  0000000000000018          29    18     8
  [29] .strtab           STRTAB           0000000000000000  000033a0
       00000000000001da  0000000000000000           0     0     1
  [30] .shstrtab         STRTAB           0000000000000000  0000357a
       000000000000011a  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)

ELFを分解する

ELF ファイルは通常のテキスト ファイルとして開くことができないため、ELF ファイルに含まれる命令やデータを直接表示する場合は、逆アセンブリの方法を使用する必要があります。
objdump -D で逆アセンブルします

objdump -D test

上記のコマンドによって返される結果の一部は次のとおりです。

0000000000001149 <main>:
    1149:       f3 0f 1e fa             endbr64
    114d:       55                      push   %rbp
    114e:       48 89 e5                mov    %rsp,%rbp
    1151:       48 83 ec 10             sub    $0x10,%rsp
    1155:       89 7d fc                mov    %edi,-0x4(%rbp)
    1158:       48 89 75 f0             mov    %rsi,-0x10(%rbp)
    115c:       48 8d 05 a1 0e 00 00    lea    0xea1(%rip),%rax        # 2004 <_IO_stdin_used+0x4>
    1163:       48 89 c7                mov    %rax,%rdi
    1166:       e8 e5 fe ff ff          call   1050 <puts@plt>
    116b:       b8 00 00 00 00          mov    $0x0,%eax
    1170:       c9                      leave
    1171:       c3                      ret

objdump -S を使用して逆アセンブルし、C 言語のソース コードを表示します (コンパイル時に -g オプションを追加する必要があります)。

objdump -S test

上記のコマンドの完全な結果は次のとおりです。

test:     file format elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:       f3 0f 1e fa             endbr64 
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__@Base>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   call   *%rax
    1016:       48 83 c4 08             add    $0x8,%rsp
    101a:       c3                      ret    

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:       ff 35 9a 2f 00 00       push   0x2f9a(%rip)        # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:       f2 ff 25 9b 2f 00 00    bnd jmp *0x2f9b(%rip)        # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:       0f 1f 00                nopl   (%rax)
    1030:       f3 0f 1e fa             endbr64 
    1034:       68 00 00 00 00          push   $0x0
    1039:       f2 e9 e1 ff ff ff       bnd jmp 1020 <_init+0x20>
    103f:       90                      nop

Disassembly of section .plt.got:

0000000000001040 <__cxa_finalize@plt>:
    1040:       f3 0f 1e fa             endbr64 
    1044:       f2 ff 25 ad 2f 00 00    bnd jmp *0x2fad(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    104b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001050 <puts@plt>:
    1050:       f3 0f 1e fa             endbr64 
    1054:       f2 ff 25 75 2f 00 00    bnd jmp *0x2f75(%rip)        # 3fd0 <puts@GLIBC_2.2.5>
    105b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .text:

0000000000001060 <_start>:
    1060:       f3 0f 1e fa             endbr64 
    1064:       31 ed                   xor    %ebp,%ebp
    1066:       49 89 d1                mov    %rdx,%r9
    1069:       5e                      pop    %rsi
    106a:       48 89 e2                mov    %rsp,%rdx
    106d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1071:       50                      push   %rax
    1072:       54                      push   %rsp
    1073:       45 31 c0                xor    %r8d,%r8d
    1076:       31 c9                   xor    %ecx,%ecx
    1078:       48 8d 3d ca 00 00 00    lea    0xca(%rip),%rdi        # 1149 <main>
    107f:       ff 15 53 2f 00 00       call   *0x2f53(%rip)        # 3fd8 <__libc_start_main@GLIBC_2.34>
    1085:       f4                      hlt    
    1086:       66 2e 0f 1f 84 00 00    cs nopw 0x0(%rax,%rax,1)
    108d:       00 00 00 

0000000000001090 <deregister_tm_clones>:
    1090:       48 8d 3d 79 2f 00 00    lea    0x2f79(%rip),%rdi        # 4010 <__TMC_END__>
    1097:       48 8d 05 72 2f 00 00    lea    0x2f72(%rip),%rax        # 4010 <__TMC_END__>
    109e:       48 39 f8                cmp    %rdi,%rax
    10a1:       74 15                   je     10b8 <deregister_tm_clones+0x28>
    10a3:       48 8b 05 36 2f 00 00    mov    0x2f36(%rip),%rax        # 3fe0 <_ITM_deregisterTMCloneTable@Base>
    10aa:       48 85 c0                test   %rax,%rax
    10ad:       74 09                   je     10b8 <deregister_tm_clones+0x28>
    10af:       ff e0                   jmp    *%rax
    10b1:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    10b8:       c3                      ret    
    10b9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

00000000000010c0 <register_tm_clones>:
    10c0:       48 8d 3d 49 2f 00 00    lea    0x2f49(%rip),%rdi        # 4010 <__TMC_END__>
    10c7:       48 8d 35 42 2f 00 00    lea    0x2f42(%rip),%rsi        # 4010 <__TMC_END__>
    10ce:       48 29 fe                sub    %rdi,%rsi
    10d1:       48 89 f0                mov    %rsi,%rax
    10d4:       48 c1 ee 3f             shr    $0x3f,%rsi
    10d8:       48 c1 f8 03             sar    $0x3,%rax
    10dc:       48 01 c6                add    %rax,%rsi
    10df:       48 d1 fe                sar    %rsi
    10e2:       74 14                   je     10f8 <register_tm_clones+0x38>
    10e4:       48 8b 05 05 2f 00 00    mov    0x2f05(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable@Base>
    10eb:       48 85 c0                test   %rax,%rax
    10ee:       74 08                   je     10f8 <register_tm_clones+0x38>
    10f0:       ff e0                   jmp    *%rax
    10f2:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    10f8:       c3                      ret    
    10f9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001100 <__do_global_dtors_aux>:
    1100:       f3 0f 1e fa             endbr64 
    1104:       80 3d 05 2f 00 00 00    cmpb   $0x0,0x2f05(%rip)        # 4010 <__TMC_END__>
    110b:       75 2b                   jne    1138 <__do_global_dtors_aux+0x38>
    110d:       55                      push   %rbp
    110e:       48 83 3d e2 2e 00 00    cmpq   $0x0,0x2ee2(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    1115:       00 
    1116:       48 89 e5                mov    %rsp,%rbp
    1119:       74 0c                   je     1127 <__do_global_dtors_aux+0x27>
    111b:       48 8b 3d e6 2e 00 00    mov    0x2ee6(%rip),%rdi        # 4008 <__dso_handle>
    1122:       e8 19 ff ff ff          call   1040 <__cxa_finalize@plt>
    1127:       e8 64 ff ff ff          call   1090 <deregister_tm_clones>
    112c:       c6 05 dd 2e 00 00 01    movb   $0x1,0x2edd(%rip)        # 4010 <__TMC_END__>
    1133:       5d                      pop    %rbp
    1134:       c3                      ret    
    1135:       0f 1f 00                nopl   (%rax)
    1138:       c3                      ret    
    1139:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001140 <frame_dummy>:
    1140:       f3 0f 1e fa             endbr64 
    1144:       e9 77 ff ff ff          jmp    10c0 <register_tm_clones>

0000000000001149 <main>:
#include<stdio.h>

int main(int argc, char *argv[])
{
    
    
    1149:       f3 0f 1e fa             endbr64 
    114d:       55                      push   %rbp
    114e:       48 89 e5                mov    %rsp,%rbp
    1151:       48 83 ec 10             sub    $0x10,%rsp
    1155:       89 7d fc                mov    %edi,-0x4(%rbp)
    1158:       48 89 75 f0             mov    %rsi,-0x10(%rbp)
    printf("hello world\r\n");
    115c:       48 8d 05 a1 0e 00 00    lea    0xea1(%rip),%rax        # 2004 <_IO_stdin_used+0x4>
    1163:       48 89 c7                mov    %rax,%rdi
    1166:       e8 e5 fe ff ff          call   1050 <puts@plt>

    return 0;
    116b:       b8 00 00 00 00          mov    $0x0,%eax
    1170:       c9                      leave  
    1171:       c3                      ret    

Disassembly of section .fini:

0000000000001174 <_fini>:
    1174:       f3 0f 1e fa             endbr64 
    1178:       48 83 ec 08             sub    $0x8,%rsp
    117c:       48 83 c4 08             add    $0x8,%rsp
    1180:       c3                      ret 

おすすめ

転載: blog.csdn.net/tyustli/article/details/130549434