0

アセンブリに 1 つ、C に 1 つの 2 つのソース ファイルがあります。アセンブリには、c ソース内の静的文字列への参照が含まれています。C ソースから呼び出される関数をアセンブリに定義すると、問題なく正常に動作します。しかし、アセンブリから printf を呼び出して、c ソース ファイルから文字列を引数として渡そうとすると、出力が文字化けするか、まったく出力されません。

nasm を使用してアセンブリを elf32-i386 にコンパイルし、gcc を使用して c ファイルをコンパイルします。幸いなことに、デバッグ情報の有無にかかわらず試してみましたが、同じ結果が得られました。

簡単なソースファイルは次のとおりです。

メイン:

SECTION .text

global s_func
extern c_str
extern printf

s_func:
    sub esp, 4
    mov dword [esp], c_str
    call printf
    add esp, 4
    ret

main.c:

#include <stdio.h>
const char* c_str = "Sup."; 
extern void s_func(void);

int main(void)
{
    printf(c_str); //prints as expected
    s_func(); //weird stuff
}

メイクファイル:

main : main.o main.s.o
    gcc main.o main.s.o -o main

main.o :
    gcc -g -c main.c -o main.o
main.s.o :
    nasm -f elf main.s -o main.s.o

これらの 2 つのファイルをオブジェクトにコンパイルしてからリンクすると、printf の呼び出しはどちらのソースでも同じであることがわかります。コード セグメントは同じで、両方のアセンブリ リストで c_str に同じアドレスが含まれています。

main.c を呼び出します。

    printf(c_str); //prints as expected
 80483ed:   a1 14 a0 04 08          mov    0x804a014,%eax
 80483f2:   89 04 24                mov    %eax,(%esp)
 80483f5:   e8 06 ff ff ff          call   8048300 <printf@plt>

main.s を呼び出す

08048410 <s_func>:
 8048410:   83 ec 04                sub    $0x4,%esp
 8048413:   b8 14 a0 04 08          mov    $0x804a014,%eax
 8048418:   89 04 24                mov    %eax,(%esp)
 804841b:   e8 e0 fe ff ff          call   8048300 <printf@plt>
 8048420:   83 c4 04                add    $0x4,%esp
 8048423:   c3                      ret    

多分私はいくつかのレジスタを保存すると思いますか?s_func で通常のスタックフレームをセットアップしましたが、それでも失敗します。

4

1 に答える 1

0

オブジェクトファイルのリンク中に問題があると思います(アセンブリで印刷を使用しているため)。

Cライブラリのprintfを利用する関数を含むGASアセンブリを作成し、asコマンドでアセンブルするのが一番良い方法だと思います。

次に、gcc コンパイラを使用して c コードをコンパイルし、次のコマンドを使用して、GAS が作成したオブジェクト ファイルを 1 行でリンクします。

GASが作成したオブジェクトファイルがmain_s.oの場合、

gcc main_c.c main_s.o -o main

したがって、gcc は最初に main_c.c のオブジェクト形式を作成し、次に main_c.o と main_s.o の両方をリンクします。これにより、正しいリンクされた elf ファイルが得られます。

于 2012-04-26T05:58:09.067 に答える