アセンブリに 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 で通常のスタックフレームをセットアップしましたが、それでも失敗します。