マイコンを正しく操縦するための作法

基礎から学ぶ C 言語講座
岡田 好一
Yoshikazu Okada

６回 メモリ割り当てとスタック管理を攻略しよう

第本稿で使用する R8C/1B の ROM は 16 K バイト＋2 K バイト，RAM は 1 K バイトです．

● ROM 上のプログラム
R8C のようなマイコンでは，プログラムは ROM にマイコンでは記憶域が限られているため，意識して書き込むのが普通で，その前提で IC もコンパイラもROM と RAM の使い分けが必要です．素直にコンパイルすると C 言語のプログラムは ROM 上に配置され設計されています．
C 言語には，「ソース・プログラムから翻訳されたるので，データをどうするかが問題になります．まず，主記憶の構成から復習しましょう．

機械語プログラムは，実行中は不変である」という前提があります．そのため，ROM との相性は良いのです．

本連載で使用中の Renesas Starter Kit for R8C/1Bの入手方法は稿末をご覧ください〈編集部〉．

本連載で使用している R8C/1B の 16 K バイト版では， 0C000h 〜 0FFFFh までの 16 K バイトにプログラム用の ROM が用意されています．16 K バイトの容

主記憶の構成量は，多数の固定データを詰め込もうとしない限り，1 システムとしては使いでがあります．

R8C/1B（16 K バイト ROM タイプ）のメモリ配置図を図 6 − 1 に示します．

もちろん，RAM にプログラムを置くのは反則ではないし，動くはずです．クロック数が厳しい場合など，プログラムが自分で機械語プログラムを書いて制御を● 周辺機能を制御するためのレジスタ SFR
ア ド レ ス 空 間 の 最 初 の 7 6 8 バ イ ト（ 00000h 〜渡すという（自己書き換えプログラム），アクロバット的なプログラムが思い浮かぶかもしれません．が，あ002FFh）は SFR（Special Function Registers）と呼ばくまで例外でしょう．

れ，入出力ポートやタイマなどの周辺機能を制御するためのレジスタが配置されています．いわゆるメモ
リ・マップト入出力です．
割り込み系を除くと，ここはプログラムにとっては外界との唯一の窓口です．ポート（港）の言葉が言い得て妙です．

RAM とその使われ方
R8C/1B の 16 K バイト ROM 版では， 0400h 〜07FFh に 1 K バイトの RAM が用意されています．
R8C では CPU の速度と ROM/RAM の速度は均衡し仮想記憶（virtual memory / virtual storage）
複数のプログラムが並行して走るマルチタスクの場合，には実メモリが必要ですから，プログラムが仮想記憶にア

互いの干渉を避けるためにはメモリを分離する必要がありクセスすると実メモリが割り当てられているかが判定され，ます．仮想記憶は，一般のソフトウェア，つまりプログラ退避されていれば実メモリに戻されますし，退避されていムから見える記憶領域で，別のプログラムで同じ番地を使なければ実領域が生成されます．この定義では，仮想記憶用しても，別の記憶として扱われるしかけです．と実記憶の大きさは限定されていないので，仮想記憶の方

OS から見ると，個々のプログラムのアドレスと物理メモリと退避のためのディスク領域を結びつけるしかけです．
プログラムのアドレスと物理メモリの対応はハードウェアが狭い場合もありえます．
マイコンでも処理が複雑かつ高度化されるにつれ，仮想記憶が必要とされるでしょう．

化されていて，MMU（Memory Management Unit）と呼ばれるハードウェア機構が管理します．プログラムが実働する

192

2006 年 11 月号

00000h スペシャル・ファンクション・レジスタ（SFR）
002FFh
大域変数

00400h007FFhstatic局所変数

内部RAM（1Kバイト）

02400h027FFh02800h

内部ROM（データ・フラッシュ）
ブロックA（1Kバイト）

ユーザ・スタック

ブロックB（1Kバイト）

割り込みスタック

02BFFhヒープ領域

0C000h

内部ROM（プログラムROM）
ブロック1（8Kバイト）

0DFFFh0E000h0FFDCh0FFFFhブロック2（8Kバイト）（固定割り込みベクタ・テーブル）FFFFFh拡張領域（使わない）

図 6 − 1 R8C/1B（16 K バイト ROM タイプ）のメモリ配置図
R8C は上位機種の M16C の CPU を引き継いでいるので，データは 16 ビット・アドレス内（64 K バイト），プログラムは20 ビット・アドレス内（1 M バイト）に配置されているていますから，速度に関しては使用上の注意はありま

第 2 の用途は，CPU 内のレジスタで作業記憶が足りない場合のデータの一時退避用です．この場合，機せん．

械語の push 命令と pop 命令が使われます．
● システム・スタック
R8C 自体の動作に最小限必要な RAM 領域は，割り込みスタック領域です．簡単なシステムですべてアセ● ユーザ・スタックンブラで組むならば，最初に割り込みスタック・ポイ

ムでは，一般ユーザのスタック領域が別に設定されまンタ（ISP）の値を設定し，そのまま割り込みスタック領域を使い続けるのがシンプルです．

す．通常のプログラムはユーザ・スタック領域，割り込みルーチンは割り込みスタック領域と使い分けます．

システム・スタックの第 1 の用途は，サブルーチンや割り込み処理ルーチンの終了時に，復帰すべき命令

ユーザ・スタックを利用するには，フラグ・レジスタ（FLG）の U フラグをセットします．セットするコーへのアドレスの一時記憶です．復帰するときには，そドが，自動生成されるスタートアップ・プログラムにのアドレスがプログラム・カウンタに格納されます．
特に設定しない限り，通常のサブルーチンでも割り込入っています．
スタックの使い分けはハードウェアが行います．割

みルーチンでも ISP が使われ，ユーザ・スタック・ポインタ（USP）は使われません．

り込み処理ルーチンは，自動的に割り込みスタック領域を使うことになります．割り込み処理が終了すると，本稿で使用している純正の C 言語による開発システ

自己書き換えプログラム
通常の計算機言語では，プログラムとデータは分離しているので，実行中にプログラムが変わりうるのは，やむを得ぬ離れ業として以外は，にわかには信じ難い話に思えます．

（もっとも，OS レベルではアップデートなどと称して，日常茶飯事のできごとだが）．
マイコンでプログラムの固定が可能なのは，アドレス・レジスタなどの間接指定のしくみがあるからです．経験上，しかし，歴史的にはごく初期からデータとプログラムの境界をなくす方向の動きがあり，計算機言語にも対応するしかけがあります．
例えば，LISP ではインタプリタ自身を eval 関数で呼び配列で済む場合はその範囲で，もう少し柔軟に対応したい場合はポインタを利用します．
プログラムでインタプリタやシミュレータを書くのはもちろん可能ですから，結局は程度問題になります．

出すことができます．それどころか，PROLOG では自分自身が作ったプログラムを自分に追加することができます2006 年 11 月号

193