2012-03-22 33 views
4

アセンブラで書かれた関数Reset_Handler()をデバッグしようとしています(私は理解できませんが、標準ライブラリの一部として提供されています)。 GDBを使用して、私はniを使ってすべての単一命令を実行します。ここで私が得るものです:プログラムカウンタが進まない

効果で
(gdb) ni 
0x08005dc4 in Reset_Handler() 
(gdb) ni 
0x08005dc6 in Reset_Handler() 
(gdb) ni 
0x08005dc6 in Reset_Handler() 
(gdb) ni 
0x08005dc6 in Reset_Handler() 
(gdb) ni 
0x08005dc6 in Reset_Handler() 

、プログラムポインタは0x08005dc6の「スタック」を取得します。これは正常な動作ですか、または私が行うたびにプログラムポインタが前進するべきですかni?以下はReset_Handler()の始まりです:

.section .text.Reset_Handler 
    .weak Reset_Handler 
    .type Reset_Handler, %function 
Reset_Handler: 

/* Copy the data segment initializers from flash to SRAM */ 
    movs r1, #0 
    b LoopCopyDataInit 

CopyDataInit: 
    ldr r3, =_sidata 
    ldr r3, [r3, r1] 
    str r3, [r0, r1] 
    adds r1, r1, #4 

LoopCopyDataInit: 
    ldr r0, =_sdata 
    ldr r3, =_edata 
    adds r2, r0, r1 
    cmp r2, r3 
    bcc CopyDataInit 
    ldr r2, =_sbss 
    b LoopFillZerobss 
/* Zero fill the bss segment. */ 
FillZerobss: 
    movs r3, #0 
    str r3, [r2], #4 

EDIT:ここでは逆アセンブルされた命令である:

disas 
Dump of assembler code for function Reset_Handler: 
    0x08005dc0 <+0>:  movs r1, #0 
    0x08005dc2 <+2>:  b.n  0x8005dcc <LoopCopyDataInit> 
    0x08005dc4 <+4>:  ldr  r3, [pc, #40] ; (0x8005df0 <LoopFillZerobss+16>) 
=> 0x08005dc6 <+6>:  ldr  r3, [r3, r1] 
    0x08005dc8 <+8>:  str  r3, [r0, r1] 
    0x08005dca <+10>: adds r1, #4 
    0x08005dcc <+0>:  ldr  r0, [pc, #36] ; (0x8005df4 <LoopFillZerobss+20>) 
    0x08005dce <+2>:  ldr  r3, [pc, #40] ; (0x8005df8 <LoopFillZerobss+24>) 
    0x08005dd0 <+4>:  adds r2, r0, r1 
    0x08005dd2 <+6>:  cmp  r2, r3 
    0x08005dd4 <+8>:  bcc.n 0x8005dc4 <Reset_Handler+4> 
    0x08005dd6 <+10>: ldr  r2, [pc, #36] ; (0x8005dfc <LoopFillZerobss+28>) 
    0x08005dd8 <+12>: b.n  0x8005de0 <LoopFillZerobss> 
    0x08005dda <+0>:  movs r3, #0 
    0x08005ddc <+2>:  str.w r3, [r2], #4 
    0x08005de0 <+0>:  ldr  r3, [pc, #28] ; (0x8005e00 <LoopFillZerobss+32>) 
    0x08005de2 <+2>:  cmp  r2, r3 
    0x08005de4 <+4>:  bcc.n 0x8005dda <FillZerobss> 
    0x08005de6 <+6>:  bl  0x8005c64 <SystemInit> 
    0x08005dea <+10>: bl  0x8000184 <main> 
    0x08005dee <+14>: bx  lr 
End of assembler dump. 
+0

スタックポインタまたはプログラムカウンタ? 0x08005dc6には何がありますか? RAMのような匂い。自動表示がスタックポインタの場合は、プログラムカウンタとディスアセンブル命令に変更してください。コントロールが典型的なデフォルトのアボートハンドラに転送された場合、そのハンドラは通常は単純な「自分自身へのジャンプ」ループであるため、SPは変更されません。 –

+0

@MartinJames:申し訳ありませんが、それはプログラムカウンタです。 – Randomblue

+1

Hmmm。r3を読み込んでもエキサイティングなことはありません:(実際にあなたが見ているのは、実際にあなたが思うものですか?私は間違ったバージョンのソースファイル、マップファイル –

答えて

4

、私は_sidataでのアドレスであることを推測すると思います無効。 _sidatar3にロードされるので、

ldr  r3, [r3, r1] 

が実行されたときに、無効なアクセスは、それが再びその命令にヒットするまで実行する他のプロセッサのリセットを引き起こします。またはそのようなもの。

_sidataの内容を確認してください。


いくつかの追加の注意事項:

私はアドレスXXXXの命令をr0を使用していますが、r0reset_handler()に初期化されている場所を、私は見ていないことがわかります。 reset_handler()を呼び出すコードで既にr0が正しく設定されている可能性がありますが、リセットベクターが実際に指し示す例外ベクトルテーブルとコードを確認する必要があります。 (私はこれがARM7またはこれに類するものと仮定しています。私が間違って推測したかどうか知ろう)例外ベクトルテーブルは、リセット時に_startという名前のラベルにベクトル化するようなものです:

.global __vectors 
__vectors: 
ldr  pc, [pc, #24] /* Reset */ 
ldr  pc, [pc, #24] /* Undefined instruction */ 
ldr  pc, [pc, #24] /* Software interrupt */ 
ldr  pc, [pc, #24] /* Prefetch abort */ 
ldr  pc, [pc, #24] /* Data abort */ 
ldr  pc, [pc, #24] /* Reserved */ 

/* 
* On IRQ the PC will be loaded from AIC_IVR, which 
* provides the address previously set in AIC_SVR. 
* The interrupt routine will be called in ARM_MODE_IRQ 
* with IRQ disabled and FIQ unchanged. 
*/ 
ldr  pc, [pc, #-0xF20] /* Interrupt request, auto vectoring. */ 
ldr  pc, [pc, #-0xF20] /* Fast interrupt request, auto vectoring. */ 

.word _start 
.word __undef 
.word __swi 
.word __prefetch_abort 
.word __data_abort 
+0

あなたは '_sidata'が無効なアドレスであることが正しいと思います。 'r0'の初期化に関しては、' LoopCopyDataInit'の最初の行にあると思います。 (リセットハンドラは2番目の命令として 'LoopCopyDataInit'を呼び出します。) – Randomblue

+0

r3のロードによってデータアボートが発生した場合、それを識別するシングルステップではありませんか? –

+0

@MartinJames:そうだと思いますが、 'ldr r3、[r3、r1]'でシングルステップを実行するとプログラムカウンタが前進することも期待しています!私は、使用されているツールチェーンや例外ベクトルがどのように設定されているかはわかりません。私は長い間、OpenOCD JTAGドライバとARM7をターゲットとしたEclipseのGDB用の古いZylin CDTプラグインを使いこなしていたことを知っていますが、常に安定した動作をするとは限りませんでした。 –

1

まあ、それはそれは時を依存何

です:-)依存指示は0x08005dc6です。リセットハンドラでは、次のような命令がある可能性があります。

0x08005dc6 jmp 0x08005dc6 

これはその動作を示します。

あなたは、のようなもので、その場所実際
だものを見るためにチェックする必要があり

:あなたが投稿したコードや分解に基づいて

disas 0x08005dc6 0x08005dcf 
+0

本当にプログラムカウンターです、ありがとうございます。その特定の場所で命令を確認するにはどうすればいいですか?objdumpを使うべきですか? – Randomblue

+1

@Randomblue、 'objdump'、いいえ、あなたがマゾイストでない限りです:-) 'ni'コマンドを使って既に' gdb'を実行していますので、私のアップデートに従って 'disas'コマンドを使用してください。 – paxdiablo

+0

私は逆アセンブリのダンプで質問を更新しました。 – Randomblue

関連する問題