まず、C言語のコードファイルmstore.cを次のように記述します。
#include <stdio.h>
long mult2(long, long);
void multstore(long x, long y, long *dest) {
long t = mult2(x, y);
*dest = t;
}
コマンドラインで「-S」オプションを使用して、C言語コンパイラによって生成されたアセンブリコードを確認します。
PS E:\VS Code\VS Code C\chapter 3> gcc -S mstore.c
これにより、GCCはコンパイラを実行し、アセンブリファイルmstore.sを生成しますが、それ以上の作業は行いません。(通常、オブジェクトコードファイルを生成するためにアセンブラを呼び出し続けます)。
.file "mstore.c"
.text
.globl multstore
.def multstore; .scl 2; .type 32; .endef
.seh_proc multstore
multstore:
pushq %rbx
.seh_pushreg %rbx
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
movq %r8, %rbx
call mult2
movl %eax, (%rbx)
addq $32, %rsp
popq %rbx
ret
.seh_endproc
.ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0"
.def mult2; .scl 2; .type 32; .endef
「-C」コマンドラインオプションを引き続き使用すると、GCCはコードをコンパイルしてアセンブルします。
PS E:\VS Code\VS Code C\chapter 3> gcc -c mstore.c
これにより、バイナリ形式のオブジェクトコードファイルmstore.oが生成されるため、直接表示することはできません。
マシンコードファイルの内容を表示するために、非常に便利な逆アセンブラと呼ばれるプログラムがあります。これらのプログラムは、マシンコードに基づいてアセンブリに似た形式を生成します。「-d」コマンドラインフラグを持つプログラムOBJDUMP(オブジェクトダンプ)は、次の役割を果たすことができます。
PS E:\VS Code\VS Code C\chapter 3> objdump -d mstore.o
結果は次のとおりです。
実際の実行可能コードを生成するには、リンカーをオブジェクトコードファイルのグループで実行する必要があり、このオブジェクトコードファイルのグループにはmain関数が含まれている必要があります。main.cファイルに次の関数があるとします。
#include <stdio.h>
void multstore(long, long, long *);
int main() {
long d;
multstore(2, 3, &d);
printf("2 * 3 --> %ld\n", d);
return 0;
}
long mult2(long a, long b) {
long s = a * b;
return s;
}
次に、次の方法を使用して実行可能ファイルprogを生成します。
PS E:\VS Code\VS Code C\chapter 3> gcc -o prog main.c mstore.c
たとえば、
ファイルprogには、2つのプロセスのコードだけでなく、プログラムの開始と終了に使用されるコード、およびオペレーティングシステムとの対話に使用されるコードも含まれています。progファイルを逆アセンブルすることもできます。
PS E:\VS Code\VS Code C\chapter 3> objdump -d prog.exe
この時点で、生成されたprogファイルを実行できます
。2つのCファイルのプログラム実行結果が期待どおりであることがわかります。
生成されたmstore.sファイル:
' .
'で始まるすべての行は、アセンブラーとリンカーに機能するように指示するディレクティブです。通常、これらの行は無視できます。私たちはこれらを削除する場合は、次のように説明してアセンブリコードは次のとおりです。
なお、以下のLinuxの環境でmstore.sファイルです
multstore:
pushq %rbx
subq $32, %rsp
movq %r8, %rbx
call mult2
movl %eax, (%rbx)
addq $32, %rsp
popq %rbx
ret