GNU X86-64コンパイル

ソースtest.cの

#include <stdio.h>

int main()
{
	printf("hello world!");
	return 0;
}

 GCC -Sのtest.cの生成test.s

	.file	"test.c"
	.text
	.def	__main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
.LC0:
	.ascii "hello world!\0"
	.text
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	$32, %rsp
	.seh_stackalloc	32
	.seh_endprologue
	call	__main
	leaq	.LC0(%rip), %rcx
	call	printf
	movl	$0, %eax
	addq	$32, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (GNU) 7.3.0"
	.def	printf;	.scl	2;	.type	32;	.endef

注アセンブラは、3つの異なる要素で構成されます。

  • 指示(指令)  コンパイラ、リンカ、デバッガ有用な構造情報を示すために、ドット数を開始します。それ自体はアセンブリ命令を示すものではありません。例えば、.FILEだけで元のソース・ファイルを記録。.DATAセグメントは、開始アドレスのデータ(区間)を表し、.textセクションは、プログラムコードの実際の開始を表します。これは、データセグメント内の文字列定数を.string表します。.globlメインラベルメインコードの他のモジュールによってアクセス可能なグローバルシンボルを示します。命令の残りの部分として、あなたは無視することができます。
  • タグ(ラベル)  コロンで終わるが、名前と場所タグラベルが表示されますを関連付けるために使用しました。例えば、ラベル.LC0は:名前の文字列が主.LC0 :. Pushq%のRBP命令は最初の命令が主な機能であることを示すラベルに続いていることを示します。慣例により、一時的なローカルラベルドットタグの開始は、コンパイラによって生成され、他のタグは、ユーザ関数とグローバル変数名に表示されます。
  • 命令(命令) 実際のアセンブリコード(pushq%RBP)、通常後退、および命令およびラベルを区別します。

 ================================== ==============データネットワーク=========================

レジスタとデータ型

16の64ビット汎用整数レジスタ約x86-64で:
十六の64ビット汎用整数レジスタ

私たちは、各プロセッサの初期バージョンは、独自の専用レジスタを持っているので、いないすべてのコマンドは、各レジスタに適用することができ、「ユニバーサル約16」と言います。設計の進展に伴い、新しい命令とアドレッシングモードが追加され、非常に多くのレジスタが等価になります。いくつかの命令が残され、特に関連する文字列処理を、そして%RSI%RDIを使用する必要があります。さらに、2個のレジスタがスタック・ポインタ、それぞれ(%のRSP)とベースポインタ(%のRBP)として保持されます。最終の8つのレジスタは、番号、特に限定されるものではありません。

長年にわたり、アーキテクチャは、各レジスタは、いくつかの内部構造を有しているので、こと、16、32に8から展開しました:
書き込み絵は、ここで説明しました

%ラックス下位8ビットは8ビット・レジスタ%のアルミニウムであり、8ビットは、単独%あああります。下位16ビットは、%斧であり、それは、低い32%のEAXで全体64ビット%のRAXあります。

登録%[8-%r15は同一の構造が、わずかに異なる命名を持っています。
書き込み絵は、ここで説明しました

単純なポイントのために、我々は唯一の64ビットのレジスタを懸念しています。しかし、ほとんどのコンパイラ製品は、32ビットおよび64ビット・モードをミックス。ほとんどのプログラムは、2 ^ 32よりも値の大きい整数必要がないので、32ビットレジスタは、整数の計算のために使用しました。64は、一般に、仮想メモリは16EBをアドレス指定することができるように、ストア・メモリ・アドレス(ポインタ)に使用されます。

アドレッシングモード

あなたは、レジスタとメモリの間でデータを移動させる第1 MOV命令、ことが理解されるべきです。多くの異なった変異体は、異なるストレージ装置間で異なるデータ型を移動させるように、複合命令セット(CISC)、MOV命令を使用してX86-64。
MOVおよびモバイルどのように決定するかだけのデータの単一文字の接頭辞として他の命令、:

書き込み絵は、ここで説明しました

異なるデータは、異なるアドレッシングモードを持っています。グローバル値(グローバル変数と関数)参照名、例えば、Xまたはprintf関数として用います。
$ 56例えば、即時に一定のドル記号を使用してください。例えばRBX%でレジスタのレジスタ名を用いて、基準値
レジスタ間接アドレッシング・メモリに格納された値に対応するアドレス値を使用され、例えば、(%RSP)ポイント%のRSPのメモリを示す値です。相対定数は、例えば、-16(%のRCX)フォワードメモリアドレス値の16のバイト指向対応リア%のRCXを表し、レジスタ値に加算され、アドレッシング基づきます。アドレッシングモードは、管理スタック、ローカル変数、関数パラメータのために重要です。多くの比較的複雑基づくアドレッシング変異体は、例えば、ある-16(%のRBX、%のRCX、 8)は、 特定の要素のサイズにアクセスするには、このアドレッシング・モードでは、アドレスに対応-16 +%RBX +%RCX * 8メモリ値を表します便利な時に配列。
以下の様々なアドレッシングモードを使用して%のRAXにロードされた64ビット値です。
%のRAXに64ビット値をロード

ほとんどの場合、同じアドレッシングモードは、レジスタおよびメモリにデータを格納するために使用することができます。しかし、すべてのモードがサポートされていません。例えば、可能な2つの比較的基づいMOVパラメータのアドレス指定を使用します:MOVQ -8(%rbx), -8(%rbx)アドレッシングモードの組み合わせをサポートするかどうかを確認するには、手動の指示を読んでする必要があります。

公開された343元の記事 ウォン称賛57 ビュー20万+

おすすめ

転載: blog.csdn.net/jadeshu/article/details/103603975