TTL でCPUを作成、16bitの手作りコンピューター TANACOM-1 誕生

FORSE

FORSE

TANACOM-1がソフトウェア黎明期を脱出し、本格的なコンピューターに変身していくのは、システムプログラムFORSEを産み出す事が必要でした。

システムプログラムFORSEとは

システムプログラムFORSEは、FORSE言語のインタープリタ、キーボード、キャラクタディスプレー、カセットインターフェース等の入出力の制御、エディタで構成されます。
これらは、今でいうOS(オペレーティングシステム)の役目をしていました。
1978年当時、一般的なマイコンの場合、外部記憶装置として、カセットテープレコーダーが主流であり、まだフロッピーディスク、ハードディスクなどのマイコン用は存在していませんでした(ミニコンやオフィスコンピュータ向けはあった)。よって、マイコン用Disk Operation Systemも開発途上であり、一般には存在していませんでした。

FORSE言語とは

FORSE とは、TANACOM-1 上で動くVTL( Very Tiny Language )系の小型言語です。
当時FORTHというプログラム言語に興味があったので、FORTH風にしようと

  1. スタックマシン
  2. 逆ポーランド記法

そして、VTLの特徴である、記号言語

今で言う「俺言語」です。

FORSEの誕生前夜

マイコン雑誌に初めて、VTL (Very Tiny Language) の記事が登場した時は、とても衝撃的でした。
モトローラ製8bitマイクロプロセッサーMC6800を搭載したマイコン「ALTAIR 680b」用に生み出された小型言語がそのVTLであり、インタープリタの大きさは何と 786 byteだったのです。
VTLは記号言語とも呼ばれ、プログラム命令が「 ! # $ % & ' ( ) = - + * : ; ? / > < , [ ] 」などの記号を使い、1記号1記号にそれぞれ意味を持たせてありました。
このVTLをヒントにその後、色々な小型言語インタープリタが色々なマイコン上に登場しました。
1978年当時マイコン雑誌では、その新しい小型言語インタープリタの記事で賑わっていました。

その頃はTANACOM-1には、VTLの様なもは存在していませんから、プログラムを一生懸命ハンドアセンブルして、モニタープログラムから16進(Hex)コードしこしこと打ち込むしかなかったのです。
そこで、意を決して、TANACOM-1用を作る事に挑戦しました。



FORSE言語 詳細


FORSE言語の特徴

①goto命令を持たない、完全な構造化言語である
②スタックオリエンテッド・マシンである

FORSE言語の仕様

注.以降『 』、~、△は説明をするため用いた表現であり、FORSE制御文字ではない。
注.黄色の四角枠の中では、例を説明する

■ FORSEの実行
アプリケーションの先頭の行から下へ評価されていく。
1行の中では、左から右へ評価されていく。



■ スタック
計算用スタックとコール用スタックを持つ。
但し、コール用スタックは、直接制御することは出来ない。
以下、スタックとは、計算用スタックを指す。

■ 真(true)と偽(false)
FORSEでは、ゼロ(0)を偽(false)、1もしくは非ゼロ(非0)を真(true)とする

◆ セパレータ
スペースとカンマ『,』はセパレータであり、10進数値の前後に置き、区別のために使用する

『1234』 は、『1234』
『12 34』は、『12』と『34』
『12,34』は、『12』と『34』



◆ 数値  符号付き16bit整数 -32768 ~ 32767



◆ 定数
10進定数 nnnnn (プログラム中には、マイナス記号を頭に付けた負の定数を書くことは出来ない)
16進定数 $nnnn
スタックアクションその定数値をスタックトップに置く

100 ・・・ 100 をスタックトップに置く
$1B2F ・・・ $1B2F をスタックトップに置く



◆ 変数
変数名は1文字で表現される、A~Zの26種。
変数は、int型であり、全てグローバル変数である
スタックアクションその値をスタックトップに置く

C ・・・ 変数Cの値をスタックトップに置く



◆ 代入文
代入演算子は『 変数名 』と表記する( 記号文字はコロン )
スタックアクションスタックトップから取り出し、その変数へ代入する
コロンと変数名の間は、空けないで下さい

100 A   100 を A に代入
C F    C の内容を F に代入



◆ 変数の間接表現
間接演算子は『 変数名 』と表記する( 記号文字はセミコロン )
その変数の持つ値とインデックスを加算した値をアドレスして、メモリを読み書きする。
これにより、配列としても使えるし、メモリへのpeek、poke命令としても使える。

$8081 Z としておき、
4Z なら、$8085番地のメモリの値をスタックトップに置く( peek命令と同じ )

代入演算子と組み合わせると、

$8081 Z としておき、
38,0Z なら、38を$8081番地のメモリへ書き込む( poke命令と同じ )
72,4Z なら、72を$8085番地のメモリへ  〃



◆ 演算

  • 『 + 』 加算。スタックのセカンドとトップを足し、答えをトップに置く
  • 『 - 』 減算。スタックのセカンドからトップを引き、答えをトップに置く
  • 『 * 』 乗算。スタックのセカンドとトップを掛け、答えをトップに置く
  • 『 / 』 除算。スタックのセカンドをトップで除し、答えをトップに置く
  • 『 % 』 剰余。スタックのセカンドをトップで除し、余りをトップに置く
  • 『・ 』 絶対値( 記号文字は真ん中点 )。スタックトップの絶対値をトップに戻す
  • 『 ' 』 乱数。スタックトップを取り出し、0~その値までのランダムな値をトップに戻す。

◆ 比較演算

  • 『 = 』 スタックのセカンドとトップを比較し、等しければ『1』を、そうでなければ『0』をトップに置く
  • 『 <> 』 スタックのセカンドとトップを比較し、等しくなければ『1』を、そうでなければ『0』をトップに置く
  • 『 > 』 スタックのセカンドがトップより大きければ『1』を、そうでなければ『0』をトップに置く
  • 『 < 』 スタックのセカンドがトップより小さければ『1』を、そうでなければ『0』をトップに置く

◆ 論理演算

  • 『 ロN 』 AND。スタックのセカンドとトップのANDしたものをトップに置く
  • 『 ロO 』 OR。スタックのセカンドとトップのORしたものをトップに置く

◆ スタック関数

  • 『 . 』 コピー( 記号文字はピリオド )。スタックトップをコピーしたものをトップに置く
  • 『 ロS 』 スワップ。スタックのセカンドとトップを入れ替える
  • 『 ロB 』 バイトストア。スタックトップをbyteアドレスとし、セカンドの内容をその位置に書き込む
  • 『 ロL 』 バイトロード。スタックトップをbyteアドレスとし、その位置にある値を読み、トップに置く

◆ キーボード入力に関するもの

  • 『 ? 』 10進入力。符号付き10進整数を入力し、スタックトップに置く
  • 『 ロ? 』 1文字入力。1文字入力し、その文字コードをスタックトップに置く
  • 『 ロG 』 GetKey。この瞬間、キーが押されてなければ0を、押されていればその文字コードをスタックトップに置く
  • 『 ロH 』 16進4桁入力。16進数4桁を入力し、スタックトップに置く

◆ ディスプレー出力に関するもの

  • 文字列出力 ダブルクォーテーションで囲まれた文字列をディスプレー表示する。

    "abcdef"  は、ディスプレーに abcdef と表示される

  • 『 \ 』 改行出力。1回改行する
  • 『 ロE 』 画面クリア。画面を消去
  • 『 ロK 』 カーソル位置セット。スタックのセカンドをX座標、トップをY座標として、そのXY位置にカーソルを移動する
  • ? 』 10進出力。スタックトップを取り出し、符号付き10進整数で表示する
    コロンと?の間は、空けないで下さい
  • 『 ロC 』 1文字出力。スタックトップを取り出し、その値を文字コードとして、その文字を表示する
  • 『 ロ$ 』 16進出力。スタックトップを取り出し、16進4桁で表示する
     

◆ 特殊関数

  • 『 & 』 マシン語コール。スタックトップをアドレスとして取り出し、そのアドレスから始まるマシン語をコールする
  • 『 ロT 』 時間調整。スタックトップをタイマーコードとして取り出し、コードに応じた時間だけ、処理を止め待機する



■ 制御構文

◆ if文

  • 『 ( ~ ) 』。スタックトップを取り出し、真(true)であれば、『~』の部分を実行する。

◆ if~else文

  • 『 ( ~ )「 △ ) 』。スタックトップを取り出し、真(true)であれば、、『~』の部分を実行し、偽(false)であれば、『△』の部分を実行する。

◆ While~Do文

  • 『 [ 条件式 # ~ 0] 』。条件式が真(true)であれば、『~』の部分を実行し、ループを繰り返す。

◆ Repeat~Until文

  • 『 [ ~ 条件式 ] 』。条件式が真(true)になるまで、『~』の部分の実行を繰り返す。

◆ END文

  • 『 @ 』 END。FORSEの評価を終了し、何かキーが押されるまで、そのまま待機する


■ 一般関数
関数名は1文字で表現される、A~Z およびア~ンの72種

  • 関数の呼び出し方法は、『 !関数名 』
  • 関数の定義は『 Λ関数名 』で、始まり、『 0] 』のリターンで定義を終わる。
    また、関数は、END文以降で定義すること


基本ソフト FORSE の使い方

基本ソフト FORSE の操作方法をご説明します。
FORSE が起動されると、常にFORSE エディトモード に入ります。
エディトモードの状態で、FORSE プログラムを書き、それから実行します。
また、書いたプログラムの修正、保存、読み出し等も行います。

エディトモードで使うコマンド

エディトモードでは、古典的なラインエディタが働いております(スクリーンエディタじゃないのです)。
プログラムテキストを行単位で、操作します。
先頭の行が「第0行」になります。
修正したい行があれば、行ポインタをそこに移動させ、修正すると云う操作の繰り返しになります。

エディトモードで使うコマンド

  • 「E」・・・ プログラムの全消去
            本当に消して良いか?の再確認はありまんので、要注意
  • 「T n」・・・ 行ポインタを第n行に移動する
            nが省略されると、トップ(第0行)に移動します。
  • 「N n」・・・ 現在の行からn行先へ、行ポインタを移動する
            nが省略されると、何もしません。
  • 「D n」・・・ 現在の行からn行削除する
            nが省略されると、何もしません。
  • 「P n」・・・ 現在の行からn行をリスト表示する
            但し、行ポイントタもリスト表示した分移動します。
            nが省略されると、全リストを表示します。
  • 「スペース xxx 」・・・ 現在の行の前に、内容を xxx とする新しい1行を追加
              これを使ってどんどんプログラムを入力していきます。
  • 「C」・・・ 現在の行を修正します。現在の行の内容がラインバッファにコピーされた後、1行入力状態になります。カーソルの「→」キーで従前の文章をなぞりながら、上書き修正出来ます。この1行内ではカーソルの「←」も使えます。但し、「↑↓」は使えません。
  • 「@」・・・ プログラムの実行
  • 「_ xxx 」・・・ その xxx をプログラムとして、この1行だけ、実行する
     例 「_ 10 3 * 5 - :?」とすれば、答えの「25」が表示されます。
  • 「M」・・・ プログラム領域の先頭byteアドレス、最終byteアドレス、現在の行の位置、空き領域の残量byte数を表示
    注.ワードアドレスではなく、10 進表示でのbyteアドレスであるから、注意されたし
  • 「R」・・・ カセットテープからプログラムを読み込む
           ( エミュレータでは、使用禁止です、暴走します)
  • 「W」・・・ カセットテープにプログラムを書き込む
           ( エミュレータでは、使用禁止です)
  • 「Q」・・・ カセットテープにマシン語とプログラムを書き込む
           ( エミュレータでは、使用禁止です)
  • 「Z n」・・・ メモリのnアドレスから、直接データ( 16進4桁)書込モードに突入
            (使用は慎重に)

(ご注意点)
1.とにかく、全てが「正しいキーしか押されないだろう、よって、誤操作の監視はしない」という「性善説」で成り立ったおりますので、ご注意ください。

2.キー入力で、「ホーム」キーを押すと、画面消去されます。これは、実行中でのキー入力でも同様です。

3.FORSE プログラムを走らせて、最後にFORSE の終了命令「@」が実行されると、プログラムが停止し、静止画面状態で、待機します。
ここで、何かキーを押してやると、はじめて、エディトモードに戻ります。
但し、何かのキーが長押しになると、エディトモードへの次の入力キーと勘違されますので、ご注意下さい。

4.プログラムの実行中に、中断させたい場合、その方法は、次の1点だけてず。
① 数値や文字入力のため、カーソルが点滅して待っている状況に於いて、「 Bksp 」(バックスペースキー)を押すと、プログラムを中断して、エディトモードに戻ってくれます。
これ以外の場合は、中断する機能がありません。やむを得ず中断したい場合は、FORSE 自身を Re-Strat するのみです。

また、この「 Bksp 」(バックスペースキー)は、エディトモードの中でも有効です。 Bksp キーを押すと、編集している行から離脱出来ます(内容は更新されず、変更したモノは破棄されます)。

5.プログラムの保存と読み込みは、カセットテープにしか行えないので、エミュレータでは、別途の機能を持たせてあります。
これに関しては、「エミュレータの使い方」でご説明いたします。


FORSE言語 入門


FORSEは逆ポーランド法です。慣れると簡単です

C言語のプログラムで例えば

a=(b+1)/(c-7);

これをFORSEでは、次のように書きます。

まず、計算式を日本語で考えると、
足したものをから引いたもので割り代入する、となります。
青の部分だけ取り出すと、
b1+ c7- / :a 代入のところだけ前後逆になりますが

これが同じ計算をするFORSEのプログラムです。
逆ポーランド法は日本語的に考えられるので、慣れると簡単です。

簡単なプログラム例

1から10までの総和を求めるプログラムでご説明いたします。
まずはC言語で書けば、

#include <stdio.h>

main()
{
  int i , sum ;
  sum=0 ;
  for ( i = 1 ; i <= 10 ; i++ ) {
   sum += i ;
  }
  printf( "SOUWA=%d\n" , sum ) ;
}

と、なります。
これを FORSE で書きますと、

0 :S  総和用変数Sを初期化
1 :I
[ SI+ :S I1+:I I 10 > ]
Iをインクリメントしながら10を越えるまで、繰り返す
”SOUWA=” SOUWA=と出力し
S :? ¥ 総和用変数Sを10進出力して、改行
@ おわる

FORSE のような記号言語は、読み辛いのが欠点ではありますが、プログラムを短く書けます。


FORSEは関数を再帰呼出しすることが出来ます。

Nの階乗を計算するプログラムを例として、ご説明します。
まずは、C言語で階乗を再帰呼出しで求めるには、

#include <stdio.h>

int kai(int n) 階乗を求める関数Kaiの定義
{
 int k;
 if ( n == 0 )
  return 1;
 k = kai( n - 1 ); kai()を再帰呼出し
 return n * k ;
}

int main() メイン関数
{
 int i, m;
 scanf("%d", &i);
 m = kai(i);
 printf("%d!=%d.\n", i, m );
 return 0;
}

と、なります。
これを、FORSE で記述すると、

? ¥
!K :?

ΛK
 :N
 N 0=( 1 )「 N N 1 - !K * )
 0]

各行を説明しますと、

? ¥ 10進入力する。そして改行
!K :? 関数Kを呼び出し、求まった答えを10進出力する
@ ここでEND
ΛK ここから階乗を求める関数Kの定義
 :N スタックより渡された引数を変数Nへ格納
 N 0=( 1 )「 N N 1 - !K * )
 Nが0だったら1を、そうでなければ、Nから1引いたもので関数Kをコールし、その答えと、積をとる。積はスタックトップに残る
 0] リターン。定義終わり

FORSE は、グローバル変数それも 26 個しか持ちませんが、引数を渡すのにスタックが使えますので、この様な関数の再帰呼出しが、簡単に実現できます。




powered by Quick Homepage Maker 5.3
based on PukiWiki 1.4.7 License is GPL. QHM

最新の更新 RSS  Valid XHTML 1.0 Transitional