あなたのコードにはいくつかの問題があります。まず、 にはアンダースコアがありますが、 にはglobal _main
ありませんmain:
。これらは一致する必要があります。全体でアンダースコアを使用するか、または-私が行うこと-まったく使用しないでください.Windowsの場合は、nasm -f win32 --prefix _ test.asm
. これにより、Linuxの場合、アンダースコアなしでアセンブルされるという点で「移植可能」に--prefix _
なります。global
Linux はアンダースコアまたはextern
記号を使用しません。たまたま、OpenWatcom C を使用していた場合は、--postfix _
. ええ、OpenWatcom は末尾のアンダースコアを使用します。ええ、C は標準化されていると彼らが言ったことは知っています。しかし、いったんボンネットの下に入ると、これは実際には真実ではありません。
もう 1 つの大きな問題は、 を呼び出した後、「スタックをクリーンアップする」_printf
必要があるadd esp, 4
(またはpop
ダミー レジスタを使用する) ことです。Windows API を使用している場合は、"callee がクリーンアップする" STDCALL 呼び出し規約を使用するため、これを行う必要はありません。C 呼び出し (CDECL 呼び出し規約) と Windows API を混在させると混乱するかもしれませんが、うまくいくはずです。
カールは gcc を使用してリンクするという正しい考えを持っていると思います。「コンパイル」するものは何もありませんが、gcc は ld への適切なコマンド ラインを認識しています。gcc -o test.exe test.obj
おそらく十分でしょう (-m32
最新の MinGW が 64 ビット コードを実行することを期待している場合は、追加することもできます)。これは、を呼び出す「起動コード」にリンクします_main
。これにより、実行可能ファイルのサイズがわずかに大きくなり、実行可能ファイルがなくてもうまくいく可能性がありますが、実行する方が簡単です。
Linux では、ld を直接使用できますが (コマンド ラインはひどいものです)、ld はエントリポイントとして_start
ではなくを探しmain
ます。ld を伝えることはできます-e main
が、このエントリポイントは呼び出されず (!)、そこret
から移動する方法はありません! Windows では状況が異なる可能性があります。最低でも、-lc
これらの C ライブラリが必要であることを ld に伝える必要があります。「gccに任せる」のが最も簡単です-.asmコードには触れません(ただし、その「起動コード」にリンクします)。ハッピーハローワールド!:)