rpi_start.Sを読む (第1回)
2013/11/04(月) 20:47 NetBSD はてブ情報 はてブに登録 はてブ数

ARMアセンブリ言語を勉強するため、CPUのスタートアップを題材にソースコードを読んでみようと思います。

といっても、ARMアセンブリ言語の知識は皆無なので、Webで一命令ずつ調べながら、わからないところは大胆に飛ばしながら読んでいくという無責任企画です。

今話題のRaspberry Piをターゲットに、少しづつ勉強していきます。

src/sys/arch/evbarm/rpi/rpi_start.Sの1.7がターゲットになります。コメント含めて328行の小さなプログラムですが、自分にとっては楽しめそうです。

さて、はじめましょう。

一番最初に実行されるエントリーポイントから読んでいきます。ソースの最初の部分は少し飛ばして、122行目からスタートです。
    122 	.global	_C_LABEL(rpi_start)
    123 _C_LABEL(rpi_start):
ラベルですね。_CとついているとCのプログラムから呼べるんでしたっけ? 先に進みましょう。
    124 	adr	r8, rpi_boot_regs
いきなりのadrはGNU asの疑似命令です。指定したレジスタにラベル(ここだとrpi_boot_regs)のアドレスをロードします。プログラムカウンタr15にadd or subして実現されているそうです。r15なんて書かれてないから不思議な感じですね。

rpi_boot_regsには
    327 rpi_boot_regs:
    328 	.space 4 * 4
と書かれています。ブート用のレジスタ(?)の領域を確保ということかな? 4*4なので32bitのアドレスを4つ確保と読むのかな。

ということで、ラベルrpi_boot_regsのアドレスをr8に読み込むという命令ですね。

adrという疑似命令は、ARMでは命令の長さが4バイトに固定されるため、32ビット(4バイト)の整数 やラベルの値(メモリアドレス)を直接レジスタに転送することができません。 とのこと。

さて次に進みます。
    125 	stmia	r8!, {r0-r3}
stmはレジスタ-メモリ転送命令の複数版です。stmはストアマルチ、ldmはロードマルチかな。iaはIncrement Afterということで、メモリアクセス後にポインタを増やす。つまり、以下のようなイメージでしょうか。
  addr = r8;
  r0 = *(addr++);
  r1 = *(addr++);
  r2 = *(addr++);
  r3 = *(addr++);
 r8!の!は最後にr8に書き戻すという意味なので
  r8 = addr;
ということなのでしょう。

rpi_boot_regがr0からr3に割り当てられたということですね。

しかし、rpi_boot_regは、どこにも使っていそうな場所がありませんね。うーん。

名前:  非公開コメント   

  • TB-URL  http://www.tokuda.net/diary/0803/tb/