LoginSignup
1
0

ORANGE pico の配列の負の添字の先に何があるのか

Last updated at Posted at 2023-12-11

ORANGE pico では、配列で宣言した最大の添字より大きい添字にアクセスしようとすると Subscript out of range というエラーになるが、0未満の添字にはエラーにならずにアクセスできる。
ただし、-30000 など、小さすぎる添字にアクセスするとリセットがかかってしまう。
そこで、リセットがかかる前の0未満の添字にアクセスし、何があるのかを観察してみた。

データの取得

今回は、以下のプログラムで0未満の添字にアクセスした。
ORANGE pico の配列には16ビットの整数が入ることがわかっているので、配列から読みだした値を十六進数4桁で出力することにした。
リセット前にきちんとデータを出力させるため、出力後に pause を入れた。
また、配列へのアクセスを行う前に、特徴的な値が入った変数をいくつか用意した。

10 a=&HDEADBEEF
20 b!=123.456
30 dim array(0)
40 i=0
50 print format$("%04x",array(i) & &HFFFF);
60 pause 10
70 i=i-1
80 goto 50

これを、uart コマンドで結果をシリアル出力するように設定した後、流し込んで実行を行った。
以下の画面は、実行直前の状態である。

実行直前の画面

実行を開始して約5分経つと、リセットがかかった。
そこで、シリアル通信で出力されたデータ (十六進数) をバイト列に変換し、さらに順番を反転させた。
From Hex, Reverse - CyberChef

プログラムでは配列の添字0に近いデータから遠いデータの順で出力している。
したがって、順番を反転したデータは配列の添字0に遠いデータから近いデータ、すなわちリセットがかかる直前の位置から配列の添字0の位置の順になっているはずである。

得られたデータ

まずは得られたデータの先頭、すなわちリセットがかかる直前の位置を見てみる。
何らかのデータがあるが、意味はよくわからない。

得られたデータ 1

しばらくゼロが連続した後、また何らかのデータが出てきた。
意味はよくわからない。

得られたデータ 2

少し進むと、大量の3が並んだデータが出てきた。
たまに0が混ざっている。

得られたデータ 3

大量の3の後には、少しの0が並んでいた。

得られたデータ 4

またゼロが連続し、しばらく進むと、文字列や変数名などのデータがポツポツある領域があった。

得られたデータ 5

この領域は、このあたりまで続いた。

得られたデータ 6

またしばらくゼロが連続し、今度は FF FF がポツポツある領域があった。
並び方には規則性があるかもしれない。

得られたデータ 7

少し進むと、入力したプログラムの文字列があった。
画面のデータ(VRAM)かと思ったが、それにしては最初に出力された部分が無い。
UARTで入力された内容かもしれない。

得られたデータ 8

少し進むと、先ほどの文字列の次のバイトの位置 0x8A01 がリトルエンディアンで格納されていた。
その次の 0xA000 と組み合わせると、ORANGE pico で使用されているマイコン PIC32MX 系の KSEG1 の RAM のアドレスになるかもしれない。

得られたデータ 9

さらに進むと、謎のデータがあった。
なんとなく昇順になっている気がする。

得られたデータ 10

さらに進むと、変数名と代入しているデータがあった。
変数 a に代入した &HDEADBEEF はビッグエンディアンで、b! に代入した 123.456 はリトルエンディアンのfloat32で格納されているようである。
よく見ると、文字列 %04x などのデータもあり、このデータは入力したプログラムを表している可能性が考えられる。

得られたデータ 11

またしばらくゼロが連続した後、謎のデータがあった。
00 A0 が並んでおり、何らかのアドレスかもしれない。

得られたデータ 12

そこから少し進むと、標準関数やコマンドの名前が並んでいる部分があった。
この位置に近いファイルオフセットと 00 A0 の組み合わせが多数見られ、線形リストなどの木構造になっている可能性が考えられる。

得られたデータ 13

今回得られたデータの最後の部分、すなわち配列の添字0の要素の直前の部分である。
変数 ab! のデータがどちらもリトルエンディアンで格納されており、その後に変数名も見られる。
さらにこの付近のファイルオフセットと 00 A0 の組み合わせも見られ、これまた線形リストなどの木構造になっている可能性が考えられる。

得られたデータ 14

考察

今回は、配列の要素を4桁の十六進数で出力した。
そしてそのデータを反転した結果、関数・コマンド・変数の名前が通常の順番で出てきた。
これは、ORANGE pico では数値はリトルエンディアンで処理されているため、4桁の十六進数で出力すると後のバイト→先のバイトの順で出力され、反転するとメモリ上の順番になるからであると考えられる。

得られたデータにはパッと見では意味がよくわからない部分もあった一方で、

  • UARTから入力されたデータ
  • プログラムのデータ
  • コマンドなどの名前が格納された構文解析などにかかわる木
  • 変数の名前やデータが格納された木

の可能性がある部分も見つかった。
今回は読み込みのみを行ったが、これらの部分にうまく書き込みを行うことで、面白い現象を起こすことができる可能性もあるかもしれない。

追加実験:メモリー配列とキャラクターパターンを探す

特徴的な変数を配置するかわりに、メモリー配列に特徴的なパターンを置いた。
さらに、これを cpoke によりキャラクターパターンとしても格納した。
DE AD BE EF が4個連続していればメモリー配列、2個連続していればキャラクターパターンと推測できる。
さらに、i が十分小さくなってからのみ pause を実行するようにすることで、効率の向上を行った。

10 mptr 8000
20 mdata &HDE,&HAD,&HBE,&HEF,&HDE,&HAD,&HBE,&HEF,&HDE,&HAD,&HBE,&HEF,&HDE,&HAD,&HBE,&HEF
30 cpoke 0,-1
40 dim array(0)
50 i=0
60 print format$("%04x",array(i) & &HFFFF);
70 if i < -25000 then pause 10
80 i=i-1
90 goto 60

同様にデータを取得した結果、0x2308 から DE AD BE EF 4個の連続が見つかった。

DE AD BE EF の連続

メモリー配列は、ここから8000を引いた 0x03c8 から格納されると推測できる。

DE AD BE EF 2個だけの連続は見つからなかった。
キャラクターパターンは今回取得した範囲には格納されていないか、自分の想定していない形式で格納されている可能性が考えられる。

追記

自分が以前書いた記事
【リ】ORANGE pico をリセットするコード|みけCAT
において、「gget コマンドで取得する幅を増やしていくと、画面上の文字が上から消えていく」という現象を報告していたことを思い出した。
ということは、キャラクターパターンは文字ごとにまとまっておらず、各文字の最初の行→各文字の次の行→…というデータ配置になっているはずである。
(もし、文字ごとにまとまっているならば、すべての文字が一部消えるのではなく、消える文字と消えない文字に分かれるはずである)
さらに、幅328で文字が消え始めたという報告があり、このときのデータサイズは $328 \times 328 \div 8 = 13448$ バイトである。
これをメモリー配列の開始アドレス 0x03c8 に加えると、0x3850 付近にキャラクターパターンのデータがありそうであることがわかる。
これを踏まえてデータを見返すと、0x3780 にデータ DE が、0x3880 にデータ AD があった。
その後も256バイトごとに DE AD BE EF のパターンがみられたので、ここがキャラクターパターンのデータと考えてよいだろう。

キャラクターパターンと考えられる場所

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0