3

最近、Linuxでx86 64ビットアセンブリをいじっていましたが、一見単純なプログラムをコンパイルした後、頭を悩ませています:P

コンパイルしてリンクしても、エラーはスローされず、Linux ELF が生成されます。実行しようとすると、次のようになります。

.:[ h4unt3r@sp3ctr4l-h0st asm ]:.
#(0)> ./hello 
bash: ./hello: No such file or directory

無効な ELF ファイルが生成されていると想定しているため、hello が存在するにもかかわらず存在しないと報告されます。理由はわかりません--おそらくこれで遊んでいきますが、これが簡単な方法で解決できるかどうか興味があります^_^

これが私のコンパイル/リンクコマンドラインです:

nasm -f elf64 hello.s -g
ld -o hello hello.o -lc

コードは次のとおりです。

section .data
    msg: db "Hello, world!",0xa,0

section .text
    extern printf
    global main

main:
    push rbp
    mov rbp, rsp

    mov rdi, msg
    xor rax, rax
    call printf
    xor rax, rax

    pop rbp
    ret

編集 -- gcc は使いたくない :)

4

3 に答える 3

4

32 ビット ハードウェアを実行していますが、64 ビットのものをテストできません。この「no such file」エラーは、32 ビット コードで見たことがあります。ld は、デフォルトで「/lib/ld-linux.so.1」を使用します。この文字列は、実行可能ファイルのプレーン テキストで確認できます。これは存在しないファイルです (明らかに「hello」はそこにあります!)。解決策は ld に伝えること-I/lib/ld-linux.so.2です。同様の解決策が 64 ビットでも機能すると思われますが、必要な「インタープリター」または「動的リンカー」がわかりません。実行可能ファイルで同様の文字列を探し、ライブラリで同様の .so を探してみてください。gcc を使用する必要はありませんが、gcc はこのようなものを見つける場所を知っています! 使いやすいかも。紛らわしいエラーですね。

(この方法で行う場合は、エントリポイントが であると予想されます_startmainこれからはできませんret-sys_exitまたはexit()を使用してください。)

「シンボルテーブル0」についてnrzが言及しているエラーに慣れていません。Nasm を意図的に変更したわけではありません。Nasm 開発者は、http://www.nasm.usやその周辺でたむろしており、フィードバックやバグ レポートをお待ちしております。(わかりました、おそらくバグレポートについて「喜んで」いません。)何かを見つけることができるかどうか見てみましょう...

-gFWIW、Nasm はデフォルトで、スイッチだけでデバッグ情報を「刺す」ようになっています。「ドワーフ」デバッグ情報を有効にするには-F dwarf...

于 2013-03-17T23:12:07.843 に答える
3

まず、 を使用するには、の代わりに とprintfリンクする必要があります。gccld

gcc -o hello hello.o

それから、別の問題は私が遭遇したのと同じかもしれません. それがバグなのか、NASM の意図的な変更なのかはわかりません。

user@computer:~/code/asm$ nasm -f elf64 hello.asm -g; gcc -o こんにちは hello.o
/usr/bin/ld: エラー: 再配置セクション 9 が予期しないシンボル テーブル 0 を使用しています
collect2: エラー: ld が 1 つの終了ステータスを返しました

YASMに移行し、この方法でアセンブルとリンクを行うことで、この問題を解決しました。

yasm -f elf64 hello.s -g dwarf2
gcc -o hello hello.o

これにより、期待される出力で実行可能ファイルが生成されます。

./hello
Hello, world!
于 2013-03-17T21:19:08.070 に答える
2

これにコードを少し変更します。

section .data
        msg:    db "Hello, world!",0xa,0
section .text
        extern  printf
 global _start
_start:
        ; RSP already 16-byte aligned, ready for a function call.
        mov     rdi,msg           ; or better, lea rdi, [rel msg]
        xor     eax, eax          ; AL=0  - no XMM args
        call    printf

        mov     rax,60  ; use _exit syscall
        mov     rdi,0   ; exit code 0
        syscall         ; call kernel

これを使用してリンクし、ld最新の GNU/Linux システムに存在しないデフォルトではなく、正しい最新の ld.so パスを設定します。

ld hello.o -o hello -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2

これは、動的にリンクされた実行可能ファイルに対してのみ機能することに注意してください。静的にリンクする場合、次のような関数が機能する前に、glibc の init 関数を手動で呼び出してそのデータ構造 (stdio バッファーなど) を初期化する必要がありますprintf

于 2017-04-04T15:03:28.063 に答える