1. ホーム
  2. linux

[解決済み] 負荷警告: エントリ シンボル _start が見つかりません

2022-02-13 14:36:14

質問

アセンブリプログラミングを勉強しています。以下は、「Hello, World!」を表示する簡単なプログラムです。このプログラムは完璧に実行されるのですが、次のような警告メッセージが表示されます。 loading

ld: 警告: エントリシンボル _start が見つかりません; デフォルトは 0000000008048080 です。

以下はそのコードです。

section .data
    msg db 'Hello, world!', 0xa
    len equ $ - msg

section .text
    global main

main:

    mov ebx, 1
    mov ecx, msg
    mov edx, len
    mov eax, 4
    int 0x80

    mov eax, 1
    int 0x80

この警告の意味を説明してくれる人はいますか?私は nasmubuntu 14 .

解決方法は?

ラベルを使用する _start の代わりに main をELFのエントリーポイントとして使用します。 main は、それがCのようなものであることを意味します。 main という関数がありますが、これは関数ですらありません(例えば はできません。 ret ).


エラーメッセージとコードから推測すると、32bitのコードを nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o

(実際に64bitのコードを作っているのであれば、たまたま動いたのはラッキーですが esp ではなく rsp .)

エラーメッセージは ld からではなく nasm . メッセージの中にそう書いてあるのです。 Timのコメントが正しいです。 ld を探します。 _start シンボルが見つからない場合は、エントリポイントをテキストセグメントの先頭に設定します。

その他、グローバル/外部シンボルを定義しても問題ありません。 main はここでは全く関係がなく、好きな場所を指すことができます。 逆アセンブルの出力とかで役に立つだけです。 あなたのコードは、もしあなたが global main / main: の行を削除したり、他の名前に変更したりすることができます。


というラベルを貼る。 main というのは、ELF のエントリーポイントは 関数ではない . それは ではなく main() を受信せず、かつ argcargv の引数であり ret を指しているため、ESPは argc は、リターンアドレスではなく


のみを使用します。 main を探す gcc / glibc の CRT スタートアップ・コードとリンクしている場合。 main シンボルを呼び出し、libcを初期化した後にそれを呼び出す(だからprintfのような関数が動く。 技術的には、ダイナミックリンカーフックによって、 libc は _start をリンクした場合、一般的には何をやっているのか正確に理解していない限り、そのようなことはしないでください)。 関連する 64ビットシステムで32ビットバイナリをアセンブルする (GNUツールチェイン)

gcc -m32 -no-pie -o hello main.o を定義した場合 main:
の代わりに gcc -m32 -static -nostdlib -o hello start.o
(これは、あなたの素の ld ).

(ここ数年、Linuxディストロは でGCCを設定しました。 -pie をデフォルトとして これは、位置に依存しないコードを望んでいるのです。 しかし、これはRIP相対アドレッシングのない32ビットモードでは本当に不便で、(たとえば、GCCのasm出力を見てください) ld は変換されません。 call printfcall printf@plt をご利用ください。 ですから、ほとんどのチュートリアルに従った手書きの asm では、従来の非 PIE 実行形式が必要で、テキストの再配置は必要ありません)。