各メニュー項目が選択された場合の処理は $\mathrm{GTO}$ 命令によって処理を分岐させ, あるいは $\mathrm{XEQ}$ 命令によってサブルーチンを呼び出すことによって実行させる.
● メニュー動作の概要
HP-42S プログラマブルメニュー画面
各メニュー項目を選択するには, それぞれに割り当てられたメニューキーを押す. たとえば上の図では, $\sum +$ キーを押すことによってメニュー $\mathrm{COMB}$ (組み合わせ), $1/x$ キーによって $\mathrm{PERM}$ (順列), $\sqrt x$ キーによって $\mathtt{N!}$ (階乗), $\mathtt{LOG}$ キーによって $\mathrm{GAM}$ (ガンマ関数), $\mathtt{LN}$ キーによって $\mathrm{RAN}$ (乱数), $\mathtt{XEQ}$ キーによって $\mathrm{SEED}$ (乱数の種) の各計算が実行される.
メニュー画面が複数存在する場合, 次のメニュー画面には $\blacktriangledown$ キーを押すことにより移動できる. また, 前のメニュー画面には $\blacktriangle$ キーを押すことにより移動できる. メニュー画面を終了するには $\mathtt{EXIT}$ キーを押す.
上の図における各々のキー $\sum +$, $1/x$, $\sqrt x$, $\mathtt{LOG}$, $\mathtt{LN}$, $\mathtt{XEQ}$, $\blacktriangle$, $\blacktriangledown$, $\mathtt{EXIT}$ には, それぞれキー番号 $1$, $2$, $3$, $4$, $5$, $6$, $7$, $8$, $9$ が割り当てられていて, この番号を用いてプログラム内から各メニューにアクセスする.
\begin{alignat*}{5}
\newcommand{\Ar}[1]{\mathrm{Ar}(#1)}
\newcommand{\Arr}[1]{\mathrm{Arr}(#1)}
\newcommand{\Card}{\text{card}}
\newcommand{\Cdot}{\,\cdot^{\mathrm{op}}}
\newcommand{\Cocone}[2]{\mathrm{Cocone}(#1,#2)}
\newcommand{\Colim}{\mathrm{colim}}
\newcommand{\CommaCat}[2]{(#1 \downarrow #2)}
\newcommand{\Cone}[2]{\mathrm{Cone}(#1,#2)}
\newcommand{\Eqclass}[4]{{#1#2#3}_{#4}}
\newcommand{\EqCls}[2]{{\left[#1\right]}_{#2}}
\newcommand{\Eqcls}[1]{\left[#1\right]}
\newcommand{\FnRest}[2]{{#1}|{#2}}
\newcommand{\Func}[2]{\mathrm{Func}(#1,#2)}
\newcommand{\g}{\varg}
\newcommand{\Hom}{\mathrm{Hom}}
\newcommand{\Id}[1]{\mathrm{id}_{#1}}
\newcommand{\Incl}[2]{\mathrm{incl}_{#1}^{#2}}
\newcommand{\InclArrow}[2]{\morphism(0,0)/>->/<450,0>[\Incl{#1}{#2} : {#1}\,\,`{#2};]}
\newcommand{\Mb}[1]{\mathbf{#1}}
\newcommand{\Mr}[1]{\mathrm{#1}}
\newcommand{\Ms}[1]{\mathscr{#1}}
\newcommand{\Mt}[1]{\mathtt{#1}}
\newcommand{\Nat}[2]{\mathrm{Nat}(#1,#2)}
\newcommand{\Ob}[1]{\mathrm{Ob}(#1)}
\newcommand{\Opp}[1]{{#1}^{\mathrm{op}}}
\newcommand{\q}{\hspace{1em}}
\newcommand{\qq}{\hspace{0.5em}}
\newcommand{\Rel}[1]{\langle{#1}\rangle}
\newcommand{\Rest}[2]{{#1}|{#2}}
\newcommand{\SkelCat}[1]{\mathrm{sk}(#1)}
\newcommand{\Slash}[1]{{\ooalign{\hfil/\hfil\crcr$#1$}}}
\newcommand{\SliCat}[2]{{#1}\,\big/\,{#2}}
\newcommand{\Src}{d^{0,\mathrm{op}}}
\newcommand{\Sub}{\mathrm{Sub}}
\newcommand{\ssqrt}[1]{\sqrt{\smash[b]{\mathstrut #1}}}
\newcommand{\Tgt}{d^{1,\mathrm{op}}}
\newcommand{\TwArCat}[1]{\mathrm{Tw}(#1)}
\newcommand{\VectCat}[1]{#1 \mathchar`- \mathbf{Vect}}
\newcommand{\Grp}{\mathbf{Grp}}
\newcommand{\Mon}{\mathbf{Mon}}
\newcommand{\POs}{\mathbf{Pos}}
\newcommand{\Set}{\mathbf{Set}}
\newcommand{\Top}{\mathbf{Top}}
\sum + &\q 1/x &\q \sqrt x &\q \Mt{LOG} &\q \Mt{LN} &\q \Mt{XEQ} &\q \blacktriangle &\q \blacktriangledown & \q\Mt{EXIT} \\
1 \qq & \q\qq 2 & 3\, & \q\qq\, 4 & 5\, & \q\qq 6 & 7 & \q\, 8 & 9 \,\qq
\end{alignat*}
● メニューの定義
以下のような手順によって, プログラム内からメニューを定義することができる.
(1) Alpha レジスターにメニューのラベルとして画面に表示するために使用する文字列を保存する. この文字列は対応するメニューキーの上のメニュー項目の名前として使われる ($\blacktriangle$ キー, $\blacktriangledown$ キー, $\Mt{EXIT}$ キーに対応するメニュー項目はディスプレイ画面内に存在しない).
(2) メニューキーを押したときに実行される処理への分岐またはサブルーチン呼び出しを $\Mr{KEYG}$ (分岐: go to) 命令または $\Mr{KEYX}$ (サブルーチン呼び出し) 命令を用いて記述する.
(3) そのメニュー項目に割り当てるメニューキーを次のいずれかの方法によって入力する:
・ $\sum +$, $1/x$, $\sqrt x$, $\Mt{LOG}$, $\Mt{LN}$, $\Mt{XEQ}$, $\blacktriangle$, $\blacktriangledown$, $\Mt{EXIT}$ のいずれかを押す.
・ キー番号 $1,\dots, 9$ のいずれかを指定する.
(4) そのメニューキーを押したときの分岐先あるいは呼び出し先のプログラムラベルを次のいずれかの方法によって記述する.
・ $\Mr{KEYG}$ 命令, $\Mr{KEYX}$ 命令の記述中に入力候補の既存のグローバルラベルがメニューとして表示されるので, その中からいずれかを選択する.
・ $\Mr{ALPHA}$ メニューを使用して, ローカルラベルまたはグローバルラベルを指定する文字列を $\Mr{ENTER} \qq label \qq \Mr{ENTER}$ によって入力する.
・ 2 桁の数値ラベル ($00,..., 99$) を指定する.
マニュアルでは, この方法によるサンプルプログラムが掲載されている. このプログラムは次のような仕様を持つ.
・ プログラムは 12 個のメニュー項目から構成される. それぞれのメニュー項目は一年の 12 の月, 1 月, 2 月,..., 12 月に対応している. 各月の略称と正式名は次のとおりである: JAN (January), FEB (February), MAR (March), APR (April), MAY (May), JUN (June), JUL (July), AUG (August), SEP (September), OCT (October), NOV (November), DEC (December).
・ メニューは 2 つのメニュー画面から構成される. つまり, 6 個のメニュー項目を持つメニュー画面が二列列存在する. 一列目は 1 月から 6 月に対応し, 二列目は 7 月から 12 月に対応する.
・ メニューキーを押すと, プログラムはそのメニューキーに対応する月の省略しない名前と月の日数をディスプレイに表示する.
※ マニュアルに掲載されているプログラムリストには, 最後の月の省略しない名前と日数を表示するサブルーチンは省略されている. この部分も補ってプログラムを完成させる.
プログラムはやや長いため, まず機能の一部だけを実現する.
以下のリストは, 上のサンプルプログラムを一画面から構成され, メニュー項目 "$\Mr{JAN}$" (1 月) のみに機能制限して実現したものである.
"$\Mr{JAN}$" メニューの下の $\sum +$ キーを押すと, 1 月の省略しない月の名前と日数を
January:31
のように表示する.● サンプルプログラム "YEAR" ── 機能制限版 (一画面一項目)
\begin{alignat*}{2}
01 & \qq\Mr{LBL}\qq\Mr{"YEAR"} & \hspace{4em} & ; \text{《グローバルラベル》: プログラム名 "YEAR".} \\
02 & \qq\Mr{LBL}\qq\Mr{A} & ~ & ; \text{《ローカルラベル》 A: 最初のメニュー画面 (今回はこの画面のみ).} \\
03 & \qq\Mr{"JAN"} & ~ & ; \text{メニュー "JAN".} \\
04 & \qq\Mr{KEY}\qq 1 \qq\Mr{XEQ}\qq 01 & ~ & ; \text{メニューキー 1 $[\Sigma +]$ を押すとラベル 01 に分岐.} \\
05 & \qq\Mr{KEY}\qq 9 \qq\Mr{GTO}\qq 99 & ~ & ; \text{メニューキー 9 [EXIT] を押すとラベル 99 に分岐.} \\
~ & ~ & ~ & ; \text{ラベル 99 のサブルーチンでメニュー終了処理を行う.} \\
06 & \qq\Mr{MENU} & ~ & ; \text{メニューインターフェースの開始.} \\
07 & \qq\Mr{LBL}\qq 20 & ~ & ; \text{《ローカルラベル》 20: メニュー表示ルーチン. ループ処理で入力待ち.} \\
08 & \qq\Mr{STOP} & ~ & ; \text{プログラムの停止. メニューキーが押されると再開.} \\
09 & \qq\Mr{GTO}\qq 20 & ~ & ; \text{ラベル 20 に分岐.} \\
10 & \qq\Mr{LBL}\qq 99 & ~ & ; \text{《ローカルラベル》 99: メニュー終了ルーチン.} \\
11 & \qq\Mr{CLMENU} & ~ & ; \text{メニューをクリアー.} \\
12 & \qq\Mr{EXITALL} & ~ & ; \text{メニューを終了.} \\
13 & \qq\Mr{RTN} & ~ & ; \text{リターン命令. 呼び出し元に処理を返す.} \\
~ & ~ & ~ & ; \text{END ではなく RTN を使う.} \\
~ & ~ & ~ & ; \text{これによりトップレベルから呼ばれた場合は END と同じくプログラム終了.} \\
~ & ~ & ~ & ; \text{しかし他のプログラムから呼び出された場合は, 呼び出し元に処理を返す.} \\
14 & \qq\Mr{LBL}\qq\Mr{01} & ~ & ; \text{《ローカルラベル》 01: "JAN" メニュー用ルーチン.} \\
15 & \qq\Mr{"January:31"} & ~ & ; \text{文字列 "January:31" を ALPHA レジスターに格納.} \\
16 & \qq\Mr{AVIEW} & ~ & ; \text{ALPHA レジスターの内容 ("January:31") を表示.} \\
17 & \qq\Mr{PSE} & ~ & ; \text{プログラムの実行を 1 秒間停止.} \\
18 & \qq\Mr{RTN} & ~ & ; \text{リターン命令. 呼び出し元に処理を返す.} \\
19 & \qq\Mr{END} & ~ & ; \text{プログラム終了.}
\end{alignat*} このプログラムの 06 行から 09 行を説明する.
\begin{alignat*}{2}
06 & \qq\Mr{MENU} & \hspace{4em} & ; \text{メニューインターフェースの開始.} \\
07 & \qq\Mr{LBL}\qq 20 & ~ & ; \text{《ローカルラベル》 20: メニュー表示ルーチン. ループ処理で入力待ち.} \\
08 & \qq\Mr{STOP} & ~ & ; \text{プログラムの停止. メニューキーが押されると再開.} \\
09 & \qq\Mr{GTO}\qq 20 & ~ & ; \text{ラベル 20 に分岐.} \\
\end{alignat*} 06 行で, ローカルラベル A で定義されたメニューを表示する. このローカルラベル A は本プログラムでは使用されない (12 か月すべてを二つのメニュー画面に分けて定義した際にメニュー画面の切り替えのために使われる).
07 行目で入力待ちのためのサブルーチンのラベル 20 を宣言する.
08 行目で $\Mr{STOP}$ 命令を実行してプログラムの処理を停止する. メニューキーが入力された場合に再開して次の 09 行目に処理を進める.
09 行目で 07 行目に分岐する. これでループ処理が行われる. ループから抜け出すのはメニューキー ([$\scriptsize{\sum} +$], [$1/x$], [$\sqrt x$], [$\mathtt{LOG}$], [$\mathtt{LN}$], [$\mathtt{XEQ}$], [$\blacktriangle$], [$\blacktriangledown$], [$\mathtt{EXIT}$] のいずれか) が入力された場合のみである.
これは割り込み処理である.
メニューキーが押されると割り込みが発生する.
プログラムがこれを捕捉して $\Mr{STOP}$ 命令によるブロックから再開する.
割り込み処理 (メニュールーチン) が実行され, 終了すると処理が戻ってくる.
ループ処理により $\Mr{STOP}$ 命令が実行されて, 再び入力待ちの状態になる.
時間はかかったが, マニュアルを読む限りこの理解でいいと思う.
プログラムの処理のイメージが掴めるととても面白い.
【このカテゴリーの最新記事】
- no image
- no image
- no image
- no image
- no image