結論
セルフ ビルドの gcc がデフォルトで thumb コードを吐くようなので -marm をつける
現象
アセンブラを含んだ SDL 版アプリをビルドすると、Illegal instruction と怒られる。
調査
.s 呼び出しテスト
単純にアセンブラ コードを呼ぶテスト アプリを作成する
メイク ファイル
Makefile
CXX = g++
RM = rm -f
TARGET = test
CFLAGS = -Wall -O3
LFLAGS =
CSRCS = ./test.cpp ./armtest.s
OBJS = $(addsuffix .o, $(basename $(CSRCS)))
LIBS =
.SUFFIXES: .cpp.o
.SUFFIXES: .s.o
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(LFLAGS) -g -o $@ $(OBJS) $(LIBS)
$(STRIP) $@
.cpp.o:
$(CXX) $(CFLAGS) -c -o $@ $<
.s.o:
$(CXX) $(CFLAGS) -c $^ -o $@
clean:
rm -f $(TARGET) $(OBJS)
マシン語 ファイル
int ArmTest(int v) { return v + 1; }
armtest.s
.text
.align 4
.global ArmTest
ArmTest:
add r0, r0, #1
mov pc, lr
C コード (main)
test.cpp
#include <stdio.h>
extern "C" int ArmTest(int v);
int main()
{
printf("Call ArmTest(2)\n");
printf("Result: %d\n", ArmTest(2));
return 0;
}
実行結果
実行結果
pomera@pomera:~/temp$ ./test
Call ArmTest(2)
Illegal instruction
pomera@pomera:~/temp$
なんで Illegal instruction?
test.cpp のアセンブリコードでは test.o が thumb コードで吐かれていた。
なので解決方法としては:
- ARM コード / thumb コードを行き来できるようにする
- gcc に -mthumb-interwork をオプションをつける
- .s は bl ではなく bx を利用する
- 全部 ARM コードにする
- gcc に -marm オプションをつける
今回は thumb コードを使わないので 2番にすることで解決。
Makefile
- CFLAGS = -Wall -O3
+ CFLAGS = -Wall -O3 -marm
実行結果
実行結果
pomera@pomera:~/temp$ ./test
Call ArmTest(2)
Result: 3
pomera@pomera:~/temp$