gcc -S -g3 -Wall -O0 -m32 -fverbose-asm ソースファイル名
-S | コンパイル本体の段階で終了する。アセンブルは行なわない。出力は、指定されたアセンブラソースでない各入力ファイルに対して、アセンブラコードファイル形式となる。 |
---|---|
-g3 | デバッグ情報のレベル 3 を出力する。レベル 3 は余分の情報を含める。例えば、プログラムに存在する全てのマクロ定義などが含まれる。 |
-Wall | ほとんどすべての警告メッセージを出力する。 |
-O0 | 最適化を行なわない。 |
-m32 | 32 ビットのアセンブラー・コードを生成する。 |
-fverbose-asm | 生成されたアセンブリコードに余分の注釈情報を加えて、読みやすくする。 |
asm ("ラベル: 命令 ソース, ディスティネーション # コメント");
asm volatile ("ラベル: 命令 ソース, ディスティネーション # コメント");
asm (" movl a, %eax"); asm (" sub b, %eax"); asm (" movl %eax, c");
asm ( " movl a, %eax \n\t" " sub b, %eax \n\t" " movl %eax, c \n\t" );
asm (" movl a, %eax \ sub b, %eax \ movl %eax, c \ ");
ラベル: 命令 ディスティネーション, ソース ; コメント
movl eax, a ; 4 バイト(ダブルワード)の領域 a の値を eax レジスターに入れる
%reg
asm (" movl $100, %eax");
$10進数 $0x16進数
asm (" movl $100, %eax");
- .SUFFIXES: .c .o .h # makefile 中で使う拡張子を設定
- NAME = sub01
- CC = gcc # コンパイラーの指定
- CFLAGS = -g3 -Wall -O0 -m32 -fverbose-asm # コンパイル・オプション
- LDFLAGS = # リンク・オプション
- INCLUDES = # コンパイル時のライブラリーの指定
- LIBS = # リンク・ライブラリーの指定
- TARGET = $(NAME).exe # 実行ファイル
- OBJS = $(NAME).o # オブジェクトファイル
- all : $(TARGET)
- $(TARGET) : $(OBJS)
- $(CC) $(OBJS) $(LIBS) -o $(TARGET) # (コマンドの前はタブ)
- .c.o: # 拡張子.c のファイルが変更されたら、拡張子.o のファイルを作成する
- $(CC) -S $(CFLAGS) $(INCLUDES) $< # アセンブルリスト出力
- $(CC) -c $(CFLAGS) $(INCLUDES) $< # (コマンドの前はタブ)
- .h.c :
- clean :
- rm $(TARGET) $(OBJS) $(NAME).s # (コマンドの前はタブ)
- /**
- * sub01.c
- * グローバル変数を使って引き算を行う。
- */
- #include <stdio.h>
- int a asm ("a") = 10;
- int b asm ("b") = 30;
- int c asm ("c");
- int main(int argc, char **argv) {
- c = 0;
- asm (" movl a, %eax");
- asm (" sub b, %eax");
- asm (" movl %eax, c");
- printf("c = %d\n", c);
- return 0;
- }
□ 実行結果
- .file "sub01.c"
- # GNU C version 3.4.2 (mingw-special) (mingw32)
- # compiled by GNU C version 3.4.2 (mingw-special).
- # GGC heuristics: --param ggc-min-expand=99 --param ggc-min-heapsize=129846
- # options passed: -iprefix -m32 -auxbase -g3 -O0 -Wall -fverbose-asm
- # options enabled: -feliminate-unused-debug-types -fpeephole
- # -ffunction-cse -fkeep-static-consts -freg-struct-return -fgcse-lm
- # -fgcse-sm -fgcse-las -fsched-interblock -fsched-spec
- # -fsched-stalled-insns -fsched-stalled-insns-dep -fbranch-count-reg
- # -fcommon -fverbose-asm -fargument-alias -fzero-initialized-in-bss
- # -fident -fmath-errno -ftrapping-math -m80387 -mhard-float
- # -mno-soft-float -malign-double -mieee-fp -mfp-ret-in-387
- # -mstack-arg-probe -maccumulate-outgoing-args -mno-red-zone
- # -mtune=pentiumpro -march=i386
- .stabs "C:/eclipse/workspace/a2/",100,0,0,Ltext0
- ...
- .stabn 162,0,0,0
- .globl a
- .data
- .align 4
- a:
- .long 10
- .globl b
- .align 4
- b:
- .long 30
- .def ___main; .scl 2; .type 32; .endef
- .section .rdata,"dr"
- LC0:
- .ascii "c = %d\12\0"
- .text
- .stabs "main:F(0,1)",36,0,11,_main
- .stabs "argc:p(0,1)",160,0,11,8
- .stabs "argv:p(0,22)=*(1,2)",160,0,11,12
- .globl _main
- .def _main; .scl 2; .type 32; .endef
- _main:
- .stabn 68,0,11,LM1-_main
- LM1:
- pushl %ebp #
- movl %esp, %ebp #,
- subl $24, %esp #,
- andl $-16, %esp #,
- movl $0, %eax #, tmp59
- addl $15, %eax #, tmp60
- addl $15, %eax #, tmp61
- shrl $4, %eax #, tmp62
- sall $4, %eax #, tmp64
- movl %eax, -4(%ebp) # tmp64,
- movl -4(%ebp), %eax #,
- call __alloca
- .stabn 68,0,11,LM2-_main
- LM2:
- call ___main #
- .stabn 68,0,13,LM3-_main
- LM3:
- movl $0, c #, c
- .stabn 68,0,14,LM4-_main
- LM4:
- /APP
- movl a, %eax
- .stabn 68,0,15,LM5-_main
- LM5:
- sub b, %eax
- .stabn 68,0,16,LM6-_main
- LM6:
- movl %eax, c
- .stabn 68,0,17,LM7-_main
- LM7:
- /NO_APP
- movl c, %eax # c, c
- movl %eax, 4(%esp) # c,
- movl $LC0, (%esp) #,
- call _printf #
- .stabn 68,0,19,LM8-_main
- LM8:
- movl $0, %eax #, <result>
- .stabn 68,0,20,LM9-_main
- LM9:
- leave
- ret
- Lscope0:
- .stabs "",36,0,0,Lscope0-_main
- .comm c, 16 # 4
- .stabs "a:G(0,1)",32,0,7,0
- .stabs "b:G(0,1)",32,0,8,0
- .stabs "c:G(0,1)",32,0,9,0
- .text
- .stabs "",100,0,0,Letext
- Letext:
- .def _printf; .scl 3; .type 32; .endef
c = -200
- /**
- * sub011.c
- * グローバル変数を使って引き算を行う。
- */
- #include <stdio.h>
- int a = 10;
- int b = 30;
- int c ;
- int main(int argc, char **argv) {
- c = 0;
- asm (" movl _a, %eax");
- asm (" sub _b, %eax");
- asm (" movl %eax, _c");
- printf("c = %d\n", c);
- return 0;
- }
- /**
- * sub02.c
- * ローカル変数を使って引き算を行う。 (ebp指定)
- */
- #include <stdio.h>
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- int c; // -12(%ebp)
- c = 0;
- asm (" movl -4(%ebp), %eax");
- asm (" sub -8(%ebp), %eax");
- asm (" movl %eax, -12(%ebp)");
- printf("c = %d\n", c);
- return 0;
- }
□ 実行結果
- .file "sub02.c"
- ...
- _main:
- .stabn 68,0,7,LM1-_main
- LM1:
- pushl %ebp #
- movl %esp, %ebp #,
- subl $24, %esp #,
- andl $-16, %esp #,
- movl $0, %eax #, tmp59
- addl $15, %eax #, tmp60
- addl $15, %eax #, tmp61
- shrl $4, %eax #, tmp62
- sall $4, %eax #, tmp64
- movl %eax, -16(%ebp) # tmp64,
- movl -16(%ebp), %eax #,
- call __alloca
- .stabn 68,0,7,LM2-_main
- LM2:
- call ___main #
- .stabn 68,0,8,LM3-_main
- LM3:
- movl $100, -4(%ebp) #, a
- .stabn 68,0,9,LM4-_main
- LM4:
- movl $300, -8(%ebp) #, b
- .stabn 68,0,12,LM5-_main
- LM5:
- movl $0, -12(%ebp) #, c
- .stabn 68,0,13,LM6-_main
- LM6:
- /APP
- movl -4(%ebp), %eax
- .stabn 68,0,14,LM7-_main
- LM7:
- sub -8(%ebp), %eax
- .stabn 68,0,15,LM8-_main
- LM8:
- movl %eax, -12(%ebp)
- .stabn 68,0,16,LM9-_main
- LM9:
- /NO_APP
- ...
c = -200
asm ("アセンブラ命令テンプレート" : "制約文字列" (出力先変数) : "制約文字列" (入力用の式や変数) : "退避したいレジスタ");
asm (" sub %2, %1" : "=a" (c) : "a" (a), "d" (b) );
- ...
- movl -4(%ebp), %eax # a, a 変数 a を eax へ設定
- movl -8(%ebp), %edx # b, b 変数 b を edx へ設定
- /APP
- sub %edx, %eax # b, a テンプレートの変換
- /NO_APP
- movl %eax, -12(%ebp) # c, c eax を変数 c へ設定
- ...
制約修飾子 | |
= | オペランドが書き込み専用であることを意味する。このオペランドに以前保持されていた値は捨てられ、出力データで置き換えられる。 |
---|---|
+ | オペランドが読み込みと書き込みの両方に使われることを意味する。 |
& | (ある特定の選択肢において)このオペランドが早期破壊 オペランドであることを意味する。早期破壊オペランドとは、命令が入力オペランドを使い終わる前に変更されるオペランドである。このため、このオペランドは、入力オペランドや任意のメモリアドレスの一部として使われるレジスタには置かれない。 |
% | このオペランドと次のオペランドが交換可能であることを指示する。 |
# | 次に続く文字からコンマまでの全ての文字を制約としては使わないことを示す。それらの文字は、レジスタ選択でのみ意味を持つ。 |
* | 次に続く文字がレジスタ選択の際には無視されることを示す。 |
単純制約文字 | |
m | メモリオペランドを指定する。その機種が一般にサポートしているアドレスならどれでも良い。 |
o | メモリオペランドを指定する。ただし、許されるアドレスは「オフセット指定可能な」アドレスだけである。 |
V | オフセット指定可能でないメモリオペランドを指定する。言い換えると、制約 m には収まるが、o には収まらないものは何でもここに入る。 |
< | 自動デクリメントのアドレスのメモリオペランドを指定する。プリデクリメントでもポストデクリメントのどちらでも良い。 |
> | 自動インクリメントのアドレスのメモリオペランドを指定する。プリインクリメントでもポストインクリメントのどちらでも良い。 |
r | レジスタオペランドが許される。ただし、レジスタは汎用レジスタである。 (i386 では、eax, ebx, ecx, edx, esi, edi) |
Intel 386 | |
q | a、b、c、d レジスタ |
A | a、d レジスタ(64ビット int 向け) |
f | 浮動小数点レジスタ |
t | 第一(スタックの一番上の)浮動小数点レジスタ |
u | 第二浮動小数点レジスタ |
a | a レジスタ |
b | b レジスタ |
c | c レジスタ |
d | d レジスタ |
D | di レジスタ |
S | si レジスタ |
I | 0〜31 の定数(32ビットのシフト用) |
J | 0〜63 の定数(64ビットのシフト用) |
K | 0xff |
L | 0xffff |
M | 0、1、2、3(lea 命令のシフト数である) |
N | 0 から 255 の範囲の定数(out 命令用) |
G | 80387 標準の浮動小数点定数 |
- /**
- * sub03.c
- * ローカル変数を使って引き算を行う。 (拡張インラインアセンブラー)
- */
- #include <stdio.h>
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- int c; // -12(%ebp)
- c = 0;
- asm (" nop # eax = a" : : "a" (a) );
- asm (" nop # edx = b" : : "d" (b) );
- asm (" sub %edx, %eax # sub %edx, %eax" );
- asm (" nop # c = eax" : "=a" (c) );
- printf("c = %d\n", c);
- return 0;
- }
□ 実行結果
- .file "sub03.c"
- ...
- LM6:
- movl -4(%ebp), %eax # a, a
- /APP
- nop # eax = a
- .stabn 68,0,14,LM7-_main
- LM7:
- /NO_APP
- movl -8(%ebp), %edx # b, b
- /APP
- nop # edx = b
- .stabn 68,0,15,LM8-_main
- LM8:
- sub %edx, %eax # sub %edx, %eax
- .stabn 68,0,16,LM9-_main
- LM9:
- nop # c = eax
- /NO_APP
- movl %eax, -12(%ebp) # tmp74, c
- .stabn 68,0,17,LM10-_main
- LM10:
- ...
c = -200
- /**
- * sub04.c
- * ローカル変数を使って引き算を行う。 (拡張インラインアセンブラー)
- */
- #include <stdio.h>
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- int c; // -12(%ebp)
- c = 0;
- asm (" sub %1, %2 # %1, %2, b, a" : "=r" (c) : "r" (b), "r" (a) );
- printf("c = %d\n", c);
- return 0;
- }
□ 実行結果
- .file "sub04.c"
- ...
- .stabn 68,0,13,LM6-_main
- LM6:
- movl -8(%ebp), %edx # b, b
- movl -4(%ebp), %eax # a, a
- /APP
- sub %edx, %eax # %edx, %eax, b, a # b, a
- /NO_APP
- movl %eax, -12(%ebp) # tmp74, c
- ...
c = -200
- /**
- * sub041.c
- * ローカル変数を使って引き算を行う。 (拡張インラインアセンブラー)
- */
- #include <stdio.h>
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- int c; // -12(%ebp)
- /* ローカル変数(拡張) */
- c = 0;
- asm ("# 4.1 ");
- asm (" sub %1, %2 # %1, %2, b, a" : "=r" (c) : "r" (b), "r" (a) );
- printf("4.1 c = %d\n", c);
- /* ローカル変数(拡張) */
- c = 0;
- asm ("# 4.2 ");
- asm (" sub %1, %2 # %1, %2, a, b" : "=r" (c) : "r" (a), "r" (b) );
- printf("4.2 c = %d\n", c);
- /* ローカル変数(拡張) */
- c = 0;
- asm ("# 4.3 ");
- asm (" sub %2, %1 # %2, %1, b, a" : "=r" (c) : "r" (b), "r" (a) );
- printf("4.3 c = %d\n", c);
- /* ローカル変数(拡張) */
- c = 0;
- asm ("# 4.4 ");
- asm (" sub %2, %1 # %2, %1, a, b" : "=r" (c) : "r" (a), "r" (b) );
- printf("4.4 c = %d\n", c);
- return 0;
- }
□ 実行結果
- .file "sub041.c"
- ...
- .stabn 68,0,14,LM6-_main
- LM6:
- /APP
- # 4.1
- .stabn 68,0,15,LM7-_main
- LM7:
- /NO_APP
- movl -8(%ebp), %edx # b, b
- movl -4(%ebp), %eax # a, a
- /APP
- sub %edx, %eax # %edx, %eax, b, a # b, a
- /NO_APP
- movl %eax, -12(%ebp) # tmp74, c
- ...
- .stabn 68,0,20,LM10-_main
- LM10:
- /APP
- # 4.2
- .stabn 68,0,21,LM11-_main
- LM11:
- /NO_APP
- movl -4(%ebp), %edx # a, a
- movl -8(%ebp), %eax # b, b
- /APP
- sub %edx, %eax # %edx, %eax, a, b # a, b
- /NO_APP
- movl %eax, -12(%ebp) # tmp79, c
- ...
- .stabn 68,0,26,LM14-_main
- LM14:
- /APP
- # 4.3
- .stabn 68,0,27,LM15-_main
- LM15:
- /NO_APP
- movl -8(%ebp), %edx # b, b
- movl -4(%ebp), %eax # a, a
- /APP
- sub %eax, %edx # %eax, %edx, b, a # a, b
- /NO_APP
- movl %eax, -12(%ebp) # tmp84, c
- ...
- .stabn 68,0,32,LM18-_main
- LM18:
- /APP
- # 4.4
- .stabn 68,0,33,LM19-_main
- LM19:
- /NO_APP
- movl -4(%ebp), %edx # a, a
- movl -8(%ebp), %eax # b, b
- /APP
- sub %eax, %edx # %eax, %edx, a, b # b, a
- /NO_APP
- movl %eax, -12(%ebp) # tmp89, c
- .stabn 68,0,34,LM20-_main
- ...
c = -200
- /**
- * sub042.c
- * ローカル変数を使って引き算を行う。 (拡張インラインアセンブラー)
- */
- #include <stdio.h>
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- int c; // -12(%ebp)
- /* ローカル変数(拡張) */
- c = 0;
- asm (" sub %2, %1 # %2, %1, c=eax, eax=a, edx=b" : "=a" (c) : "a" (a), "d" (b) );
- printf("c = %d\n", c);
- return 0;
- }
□ 実行結果
- .file "sub042.c"
- ...
- .stabn 68,0,14,LM6-_main
- LM6:
- movl -4(%ebp), %eax # a, a
- movl -8(%ebp), %edx # b, b
- /APP
- sub %edx, %eax # %edx, %eax, c=eax, eax=a, edx=b # b, a
- /NO_APP
- movl %eax, -12(%ebp) # tmp74, c
- .stabn 68,0,15,LM7-_main
- ...
c = -200
- /**
- * sub05.c
- * すべてアセンブラーで記述している関数を呼出す。
- */
- #include <stdio.h>
- extern int sub05(int x, int y) asm ("sub05");
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- printf("sub05() = %d\n", sub05(a, b));
- return 0;
- }
- /**
- * 2つの引数を加算して、その結果を戻す(すべてインラインアセンブラー)
- * @param x 被減数
- * @param y 被減数
- * @return x - y の結果
- */
- asm (
- "sub05: \n\t"
- " pushl %ebp \n\t"
- " movl %esp,%ebp \n\t"
- );
- asm (
- " movl 8(%ebp), %eax # eax = x \n\t"
- " sub 12(%ebp), %eax # eax -= y \n\t"
- );
- asm (
- " movl %ebp,%esp \n\t"
- " popl %ebp \n\t"
- " ret \n\t"
- );
□ 実行結果
- .file "sub05.c"
- ...
- .stabn 68,0,13,LM5-_main
- LM5:
- movl -8(%ebp), %eax # b, b
- movl %eax, 4(%esp) # b,
- movl -4(%ebp), %eax # a, a
- movl %eax, (%esp) # a,
- call sub05 #
- movl %eax, 4(%esp) # tmp73,
- movl $LC0, (%esp) #,
- call _printf #
- .stabn 68,0,15,LM6-_main
- LM6:
- ...
- Lscope0:
- .stabs "",36,0,0,Lscope0-_main
- /APP
- sub05:
- pushl %ebp
- movl %esp,%ebp
- movl 8(%ebp), %eax # eax = x
- sub 12(%ebp), %eax # eax -= y
- movl %ebp,%esp
- popl %ebp
- ret
- ...
c = -200
- /**
- * sub06.c
- * 連係部分以外はアセンブラーで記述している関数を呼出す。
- */
- #include <stdio.h>
- static int sub06(int x, int y);
- int main(int argc, char **argv) {
- int a = 100; // -4(%ebp)
- int b = 300; // -8(%ebp)
- printf("sub06() = %d\n", sub06(a, b));
- return 0;
- }
- /**
- * 2つの引数を加算して、その結果を戻す
- * @param x 被減数
- * @param y 被減数
- * @return x - y の結果
- */
- int sub06(int x, int y) {
- int z;
- asm (" sub %2, %1 # %2, %1, z=eax, eax=x, edx=y" : "=a" (z) : "a" (x), "d" (y) );
- return z;
- }
□ 実行結果
- .file "sub06.c"
- ...
- .stabn 68,0,13,LM5-_main
- LM5:
- movl -8(%ebp), %eax # b, b
- movl %eax, 4(%esp) # b,
- movl -4(%ebp), %eax # a, a
- movl %eax, (%esp) # a,
- call sub06 #
- ...
- sub06:
- .stabn 68,0,24,LM8-sub06
- LM8:
- pushl %ebp #
- movl %esp, %ebp #,
- subl $4, %esp #,
- .stabn 68,0,26,LM9-sub06
- LM9:
- movl 8(%ebp), %eax # x, x
- movl 12(%ebp), %edx # y, y
- /APP
- sub %edx, %eax # %edx, %eax, z=eax, eax=x, edx=y # y, x
- /NO_APP
- movl %eax, -4(%ebp) # tmp62, z
- .stabn 68,0,27,LM10-sub06
- LM10:
- movl -4(%ebp), %eax # z, z
- .stabn 68,0,28,LM11-sub06
- LM11:
- leave
- ret
- ...
c = -200