回答:
-S
gcc(またはg ++)のオプションを使用します。
gcc -S helloworld.c
これにより、helloworld.cでプリプロセッサ(cpp)が実行され、初期コンパイルが実行され、アセンブラが実行される前に停止します。
デフォルトでは、これはファイルを出力しますhelloworld.s
。-o
オプションを使用して、出力ファイルを引き続き設定できます。
gcc -S -o my_asm_output.s helloworld.c
もちろん、これは元のソースがある場合にのみ機能します。結果のオブジェクトファイルしかない場合の代替方法はobjdump
、--disassemble
オプションを設定して(または-d
省略形で)を使用することです。
objdump -S --disassemble helloworld > helloworld.dump
このオプションは、(-g
コンパイル時に)オブジェクトファイルに対してデバッグオプションが有効になっていて、ファイルが削除されていない場合に最適に機能します。
実行file helloworld
すると、objdumpを使用して取得する詳細のレベルがわかります。
.intel_syntax
はNASMと互換性がありません。それはよりMASMに似mov eax, symbol
ています(たとえばmov r32, imm32
、それがアドレスのNASMとは異なり、負荷です)が、MASMと完全に互換性もありません。特に、NASM構文で記述したい場合は、読みやすい形式として強くお勧めします。objdump -drwC -Mintel | less
またはgcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
便利です。(GCC / clangアセンブリ出力から「ノイズ」を削除する方法も参照してください)。 -masm=intel
clangでも動作します。
gcc -O -fverbose-asm -S
これにより、Cコードと行番号を組み合わせたアセンブリコードが生成され、どの行がどのコードを生成するかをより簡単に確認できます。
# create assembler code:
g++ -S -fverbose-asm -g -O2 test.cc -o test.s
# create asm interlaced with source lines:
as -alhnd test.s > test.lst
で発見されたプログラマのためのアルゴリズム、3ページ(PDFの全体の15ページです)。
as
、OS Xではこれらのフラグを認識していません。ただし、そうした場合は、-Wa
オプションをに渡すためにこれを1行で使用できますas
。
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
これの短縮版になります。
gcc -c -g -Wa,-ahl=test.s test.c
かを使用することもできますgcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
ですか?これは、値の追跡を困難にするロード/ストアでいっぱいであり、最適化されたコードがどれほど効率的であるかについては何もわかりません。
次のコマンドラインは、Christian Garbinのブログからです。
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
暗黙のキャストを含むルーチンに対して、Win-XPのDOSウィンドウからG ++を実行しました
c:\gpp_code>g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
horton_ex2_05.cpp: In function `int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'
出力は、元のC ++コードで反復されたアセンブルされた生成コードです(C ++コードは、生成されたasmストリームのコメントとして表示されます)
16:horton_ex2_05.cpp **** using std::setw;
17:horton_ex2_05.cpp ****
18:horton_ex2_05.cpp **** void disp_Time_Line (void);
19:horton_ex2_05.cpp ****
20:horton_ex2_05.cpp **** int main(void)
21:horton_ex2_05.cpp **** {
164 %ebp
165 subl $128,%esp
?GAS LISTING C:\DOCUME~1\CRAIGM~1\LOCALS~1\Temp\ccx52rCc.s
166 0128 55 call ___main
167 0129 89E5 .stabn 68,0,21,LM2-_main
168 012b 81EC8000 LM2:
168 0000
169 0131 E8000000 LBB2:
169 00
170 .stabn 68,0,25,LM3-_main
171 LM3:
172 movl $0,-16(%ebp)
-O2
gccがコードを最適化する方法を確認したい場合は、少なくとも、またはプロジェクトのビルド時に実際に使用する最適化オプションを使用してください。(または、必要に応じてLTOを使用する場合は、リンカーの出力を逆アセンブルして、実際に何が得られるかを確認する必要があります。)
表示したいものが出力のリンクに依存している場合、前述のgcc -Sに加えて、出力オブジェクトファイル/実行可能ファイルのobjdumpも役立ちます。以下は、デフォルトのobjdump構文をより読みやすいnasm構文に変換する、Loren Merrittによる非常に便利なスクリプトです。
#!/usr/bin/perl -w
$ptr='(BYTE|WORD|DWORD|QWORD|XMMWORD) PTR ';
$reg='(?:[er]?(?:[abcd]x|[sd]i|[sb]p)|[abcd][hl]|r1?[0-589][dwb]?|mm[0-7]|xmm1?[0-9])';
open FH, '-|', '/usr/bin/objdump', '-w', '-M', 'intel', @ARGV or die;
$prev = "";
while(<FH>){
if(/$ptr/o) {
s/$ptr(\[[^\[\]]+\],$reg)/$2/o or
s/($reg,)$ptr(\[[^\[\]]+\])/$1$3/o or
s/$ptr/lc $1/oe;
}
if($prev =~ /\t(repz )?ret / and
$_ =~ /\tnop |\txchg *ax,ax$/) {
# drop this line
} else {
print $prev;
$prev = $_;
}
}
print $prev;
close FH;
これはgcc -Sの出力でも使用できると思います。
mov eax,ds:0x804b794
、あまりNASMでない。また、時にはそれだけで有益な情報を取り除き:movzx eax,[edx+0x1]
メモリオペランドがあったかどうかを推測するために葉リーダーbyte
かword
。
objconv
使用します。出力ファイル= /dev/stdout
でstdoutに逆アセンブルできるので、パイプしless
て表示することができます。も存在しますがndisasm
、フラットバイナリのみが逆アセンブルされ、オブジェクトファイル(ELF / PE)については認識されません。
前述のように、-Sフラグを確認してください。
また、フラグの「-fdump-tree」ファミリー、特に「-fdump-tree-all」を確認する価値があります。これにより、gccの中間形式のいくつかを確認できます。これらは多くの場合、アセンブラーよりも読みやすく(少なくとも私にとって)、最適化パスの実行方法を確認できます。
おそらく質問が2008年からのものであるためか、回答にこの可能性はありませんが、2018年にはMatt GoldboltのオンラインWebサイトhttps://godbolt.orgを使用できます
ローカルでgit cloneして、彼のプロジェクトを実行することもできますhttps://github.com/mattgodbolt/compiler-explorer
-save-temps
これはhttps://stackoverflow.com/a/17083009/895245で言及されましたが、さらに例を挙げてみましょう。
このオプションの大きな利点は-S
、ビルド自体に大きな影響を与えることなく、任意のビルドスクリプトに非常に簡単に追加できることです。
あなたがするとき:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
そして現在、通常の出力main.o
に加えて、現在の作業ディレクトリには次のファイルも含まれています。
main.i
ボーナスであり、事前に処理されたファイルが含まれています。
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "main.c"
int myfunc(int i) {
return i + 1;
}
main.s
必要な生成されたアセンブリが含まれています:
.file "main.c"
.text
.globl myfunc
.type myfunc, @function
myfunc:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
addl $1, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size myfunc, .-myfunc
.ident "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
.section .note.GNU-stack,"",@progbits
多数のファイルに対して実行する場合は、代わりに使用することを検討してください:
-save-temps=obj
これにより、中間ファイルが-o
現在の作業ディレクトリではなくオブジェクト出力と同じディレクトリに保存されるため、潜在的なベース名の競合が回避されます。
このオプションのもう1つの優れた点は、以下を追加した場合です-v
。
gcc -save-temps -c -o main.o -v main.c
実際には、下の醜い一時ファイルの代わりに使用されている明示的なファイルが表示される/tmp
ため、前処理/コンパイル/アセンブリの手順を含む、何が行われているのかを正確に知るのは簡単です。
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s
Ubuntu 19.04 amd64、GCC 8.3.0でテスト済み。
From:http : //www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa、-a、-ad [その他のGCCオプション] foo.c> foo.lst
PhirePhlyの回答の代わりに、または誰もが言うように-Sを使用するだけです。
WindowsのCプログラムのアセンブリコードを表示/印刷する手順は次のとおりです
コンソール/ターミナル/コマンドプロンプト:
コードブロックのようなCコードエディターでCプログラムを記述し、拡張子.cで保存します。
コンパイルして実行します。
正常に実行されたら、gccコンパイラーをインストールしたフォルダーに移動し、
次のコマンドは、「.c」ファイルの「.s」ファイルを取得します
C:\ gcc> gcc -S Cファイルの完全パスENTER
コマンドの例(私の場合と同様)
C:\ gcc> gcc -SD:\ Aa_C_Certified \ alternate_letters.c
これは、元の「.c」ファイルの「.s」ファイルを出力します
4。この後、次のコマンドを入力します
C; \ gcc> cpp filename.s ENTER
コマンドの例(私の場合と同様)
C; \ gcc> cpp alternate_letters.s
これにより、Cプログラムのアセンブリ言語コード全体が出力/出力されます。
オプションとして「-S」を使用します。端末にアセンブリ出力を表示します。
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
。 -S
それ自体が作成しますfoo.s
。
以下は、gccを使用したCのソリューションです。
gcc -S program.c && gcc program.c -o output
ここで、最初の部分はプログラムのアセンブリ出力をProgramと同じファイル名で保存しますが、拡張子が.sに変更されているため、通常のテキストファイルとして開くことができます。
ここでの2番目の部分は、実際の使用のためにプログラムをコンパイルし、指定されたファイル名でプログラムの実行可能ファイルを生成します。
program.cを上記の使用は、あなたのプログラムとの名称である出力生成したい実行可能ファイルの名前です。
ところでそれはStackOverFlowの私の最初の投稿です:-}