3

ARM ベアメタル プログラムの C コードで % を使用しようとすると、libgcc のラッパーが必要になります。問題ありません。リンクできます。そうすると、リンカは不平を言うのをやめますが、mod の使用時にプログラムがハングします (レジスタを監視すると、実際には不可解な方法で循環を開始します)。% で行をコメントアウトすると、プログラムはこのようにハングしなくなります。これは間違いなく問題です。

https://gist.github.com/1724746で問題の簡単な例を作成しました

以下を使用してテストを実行します。

qemu-system-arm -M versatilepb -cpu arm1176 -nographic -kernel kernel.elf | xxd

次に ^ax で終了し、 % 行をコメントアウトすると、出力に期待するバイトが得られますが、そこに行があると、そのような出力は得られません。

ここで何が起こっているのか分かりますか?

編集:私が使用しているクロスコンパイラは、Ubuntuのデフォルトです:https ://launchpad.net/gcc-linaro

4

1 に答える 1

2

したがって、r0とr1に2をロードします(現在のタスク+1でプラス1のことを実行します)

10648:  e1a00003    mov r0, r3
1064c:  e51b1010    ldr r1, [fp, #-16]
10650:  eb00fd36    bl  4fb30 <____aeabi_uidivmod_veneer>

彼らは_veneerを使って腕から親指に切り替えたと思います。モードを切り替えるのはトランポリンです。

0004fb30 <____aeabi_uidivmod_veneer>:
   4fb30:   e51ff004    ldr pc, [pc, #-4]   ; 4fb34 <____aeabi_uidivmod_veneer+0x4>
   4fb34:   00010905    .word   0x00010905

ここに移動します。実際のモジュロ演算です。これはサムコード、サムモードです。

00010904 <__aeabi_uidivmod>:
   10904:   2900        cmp r1, #0
   10906:   d0f8        beq.n   108fa <__aeabi_uidiv+0x252>
   10908:   e92d 4003   stmdb   sp!, {r0, r1, lr}
   1090c:   f7ff fecc   bl  106a8 <__aeabi_uidiv>
   10910:   e8bd 4006   ldmia.w sp!, {r1, r2, lr}
   10914:   fb02 f300   mul.w   r3, r2, r0
   10918:   eba1 0103   sub.w   r1, r1, r3
   1091c:   4770        bx  lr
   1091e:   bf00        nop

したがって、通常の除算を実行し、結果を乗算して減算するように見えます。

12345 % 100 = 12345 - ((12345/100)*100) = 12345 - (123*100) = 12345 - 12300 = 45

問題はサムモードなのかしら。arm1176には間違いなく本物のサムモードがあり、qemuはサムを実行できます。

ただし、アセンブルとリンクを見つけるために実験を試すことができます。

.thumb
.thumb_func
.globl thumb_test
thumb_test:
   add r0,#1
   bx lr

arm-none-linux-gnueabi-as thumb_test.s -o thumb_test.o

または、ツールチェーンプレフィックスがあればそれを使用し、.oファイルを他のすべてのものにリンクします。

Cコードでそれを次のように宣言します

unsigned int thumb_test ( unsigned int );

そして、それを渡すものは何でも、その値に1を加えたものを取り戻す必要があります...モジュロの代わりにこれを試してください。

もう1つ試してみるのは、単純な除算です。除算は機能するがモジュロでは機能しないかどうかを確認してください。問題は乗算命令にあるのでしょうか。知るか。

うーん、私は問題があると思います:

0004fb30 <____aeabi_uidivmod_veneer>:
   4fb30:   e51ff004    ldr pc, [pc, #-4]   ; 4fb34 <____aeabi_uidivmod_veneer+0x4>
   4fb34:   00010905    .word   0x00010905

ldrでモードを切り替えることはできません。bxまたはblxである必要があります。アームモードでサムコードを実行しようとすると、おそらく未定義のハンドラーに移動します。

特にqemu用に書かれた、スイッチングモードがどのように機能する必要があるかについてのいくつかの例があります。これは低レベルの例です。たとえば、printfはありません。私は、uart上のものを表示する方法を備えたuart出力を持っています。これが問題である場合(サムモードへの切り替え)、プログラムをコンパイルおよびリンクする方法を調べる必要があります。以前のコードソース(現在はメンターグラフィックスによって使用されている)ツールチェーンを使用していない場合は、インターワークを指定する必要がある場合や、ツールチェーンがどのように構築されたかを理解する必要がある場合があります。これは、gnu/gccベースのものを使用していることを前提としています。

未定義のハンドラーをそこに配置する方法がある場合、またはトレースを監視して、PCがアドレス0x0000000の近くにドロップするのを確認できる場合は、おそらくこれが発生しています。私の小さなthumb_testを使用してビルドし、bxの代わりにldrを使用してそこに到達した場合、それは機能しないはずです。それでもクラッシュするはずです...

于 2012-02-02T21:56:21.137 に答える