基本情報技術者試験、アルゴリズム成長記録

基本情報技術者トップへ
午後使用教材へ
午前免除(修了試験)受験へ
午後CBT受験へ

プログラミング初心者の私は、アルゴリズムに少しずつ慣れて行った記録を付けていました。
記録と言っても日記ですと、毎日となるので、それは大変。
「月記」、月に1度学習状況を記録していました。

アルゴリズムで昨日の自分と比べた成長は分かりにくいですが、さすがに先月の自分と比べたらそれはメモに書き留めて置けました。
少しだけ恥ずかしいですが、そのメモを公開します。

尚、関連記事で言語が未記入のアルゴリズムはアセンブラで作成した自作プログラミングになります。

使用教材です。

2019年(令和元年)10月
午前対策も終盤になり、今日からアルゴリズムを始める。
まず最初に「ユークリッドの互除法」というアルゴリズムを覚えた。
引き算で最大公約数が求められるんだ。
すげー、すげー!!!

関連記事:ユークリッドの互除法

2019年11月
ユークリッドの互除法や線形探索は辛うじて出来たもの、
Tmpなどの作業領域を使って値を交換するバブルソートは頭が混乱してこんがらがる。
挿入法は、もっと分かんない。

関連記事:バブルソート挿入法
C言語でドラえもんキャラのバブルソートを作ってみた

2019年12月
作業領域Tmpを使った値の交換は、時間を掛ければ出来るようになった。
しかし、数値を数字列に変換するアルゴリズムは「1-1÷10=1」
(小数点は切り捨てられるので、1ー1÷10は、1-0.9ではなく、
1-0=1になる)が理解出来ずにトレースに半日もかかってしまった。

2020年1月
まだまだ苦手な挿入法をコツコツとトレース。

2020年2月
構造体の問題のポインタに混乱

2020年3月
基本のアルゴリズムを繰り返す

2020年5月
「アルゴリズム問題を解くコツ」で穴埋めに慣れる。
関連記事:無料教材

2020年6月
アルゴリズム問題を解くコツを会社に行く前にも解き始める。

2020年7月
「アルゴリズム問題がちゃんとわかる本」を終えて過去問演習に入ったものの、令和元年の問題にタジタジ。
ただ、解説を読んで繰り返せば理解出来る。

2020年8月
「毎日挿入法」を始めた。
毎日Javaで挿入法のプログラムのコードを模写した。
躓いているのが引数と戻り値だと気づいた。

2020年9月
アルゴリズムのプログラミング部分を拡大印刷して、自宅のトイレの壁に貼った。
ケースに入れて防水対策をした。
1人暮らしなので、怒る人はいない。

2020年10月
トレースのやり方を計算用紙で色々工夫して見た。
関連記事:飲み込みの遅い私がアルゴリズムを攻略するまで

以上になります。

基本情報技術者トップへ
午後使用教材へ
午前免除(修了試験)受験へ
午後CBT受験へ

基本情報技術者試験試験 令和2年度(令和3年1月)合格と所感

基本情報技術者試験トップへ
午前免除試験(修了試験)受験へ
午後CBT受験へ
午後使用教材へ

新型コロナの影響で中止、延期になってやっと受けられた基本情報技術者試験。
受験日令和3年1月8日、合格発表日2月26日で、無事に合格出来ました。

合格者受験番号一覧です。

スコアレポートは受験後すぐ、試験会場から駅に向かう間にメールで届きました。
この記事を書いている時点ではまだ令和2年度の試験は終わっていないので、
試験の影響しないように、スコアレポートを問題別に切り取ってこのブログに掲載します。

念の為に選択科目名は伏せて、「その1」「その2」というように掲載します。

セキュリティ(必須)

選択その1

選択その2

アルゴリズム(必須)

言語(アセンブラ選択)

という正答率でした。

1月度の合格率は、なんと58%。
10人受けたら6人ぐらいは受かるということなので、合格はうれしいのですが、
なんだかスッキリしない、モヤモヤした感じがします。

このモヤモヤ感というのは気分が良いとは言えないので、気持ちを切り替えるためにこの記事を書いています。

10人中6人も受かるから簡単なのか、余裕なのか、と言えば、そうでも無いような気がします。
ここまでモチベーション維持をして、試験会場に間に合うように行って、しっかり受験してきたということは、自分で自分にご褒美とかあげても良いのかと思います。
なので、クレープを食べました。

では、10人のうちの4人になってしまった方はというと、その方々も受験した所まで漕ぎつけた訳ですからそのことは誇りに思って欲しいです。

というと、申込したのに受験しなかった方はというと、必ずしも全員が逃げた訳ではないと思います。
避けようのない事故とか、身内に何かあったかなど様々な事情もあります。

逃げてしまった方は今度頑張ったり、自分のやりたいことを考えてみたりして行けば大丈夫だと思います。

みんなそれぞれの事情や気持ちがある中、その人の出来ることで頑張っているので、この試験を通して誰かを責めたり、試験の難易度が下がったからと言って下に見たりしないで欲しいと思います。

とは言え、平成の頃の試験ですごく大変な思いの中合格された方と同じ名称の資格取得を名乗るということに対して、何も思っていない訳では無いので、謙虚な姿勢でプログラミングを継続して学んでいきたいです。

次の目標はPythonのベンダー資格です。
応用情報に興味がない訳ではありませんが、ベンダー資格の方がより興味があります。
これは人それぞれですね。
応用情報取得を目指される方、かなり多いと思いますので、応援しています。

早くコロナが終わって欲しいです。

さて、今回の試験は試験で最も難しかったのは、モチベーションの維持でした。
そこで、モチベーション維持に心掛けたことを備忘録として書き留めます。

SNSを利用して、モチベーション維持に努めていました。
Studyplusという学習アプリを使って記録して、Twitterと連携していました。
そうすると、勉強垢の方や近い方向の方からのいいねを貰えたりするので、そのことがモチベ維持になりました。
過去問を解いたノートをこのブログで公開して、人に見せるつもりで書き貯めて行きました。それもモチベ維持に繋がりました。
関連記事:基本情報技術者試験トップ

また、自分の成長をiPhoneのメモに記録していました。
特にアルゴリズムの成長記録を時々見て、「俺、メチャメチャ頑張っている」、と自分に言い聞かせました。
関連記事:アルゴリズム成長記録

以上の対策に加え、私は女優の馬場ふみかさんのことが好きなので、FEの勉強が楽しい時、疲れた時、きっつい時も、馬場さんのことを見て励みにしていました。

モチベーション維持は、その人なりのメンタルの保ち方が大事なのかな、と思います。

基本情報技術者試験トップへ
午前免除試験(修了試験)受験へ
午後CBT受験へ
午後使用教材へ

過去問のプログラミングとトレース(アセンブラ CASL2 )

メインメニューに戻る
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)



平成21年春   平成21年秋

平成22年春   平成22年秋


平成23年特   平成23年秋


平成24年春   平成24年秋


平成25年春   平成25年秋

平成26年春   平成26年秋


平成27年春   平成27年秋


平成28年春   平成28年秋


平成29年春   平成29年秋


平成30年春   平成30年秋


平成31年春   令和元年秋

アセンブラ(CASL2)の学習は、この2冊のお蔭で、入門から過去問への対応力をメキメキ鍛えらえれました。実際に作って学べました。

入門と過去問の抜粋を解く力が鍛えられます。

過去問へ立ち向かう力が付けられます。

メインメニューに戻る
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

アセンブラ CASLⅡ 自作サンプル

メインメニューに戻る
アセンブラ過去問プログラムへ
基本情報技術者試験トップへ
これからプログラミングを始める方へ

【入門編】

シミュレータ―とおススメの本

嫌なヤツの名前とバカ!!

奇数か偶数かで「デベソ」と「ち、が、う、だ、ろ!!」

番町皿屋敷で納涼ループ

「う◎こ」をループと条件判断で取り出す

列でSTAYHOME

スタックを使って逆UNKO!

アセンブラで観光地巡り

アセンブラでデスノート風のカウントダウン

アセンブラでソーシャルディスタンス大文字変換

多重ループでドット絵おえかき(=^・^=)

アセンブラで階段を作ってみた

2進数に基数変換してみました。

クール、クーラー、クーリッシュな暗号

【アルゴリズム編】

ユークリッドの互除法を作ってみました。

うるう年の判定を作ってみました。

配列の最大値と最小値を求めてみました。

線形探索を作ってみました。

二分探索を作ってみました。

バブルソートを作ってみました。

挿入法を作ってみました。

2進数の乗算を作ってみました。

再帰呼び出しを作ってみました。

メインメニューに戻る
アセンブラ過去問プログラムへ
基本情報技術者試験トップへ
これからプログラミングを始める方へ

飲み込みの遅い私がアルゴリズムを攻略するまで

基本情報技術者試験トップ
アルゴリズム無料教材
CBT試験(午前免除午後試験)お役立ちリンク集
午前免除試験
これからプログラミングをはじめる方へ

基本情報技術者試験のアルゴリズム問題の疑似言語が読めないのは、必ず原因があって読めない、ということに気づきましたのでそれをシェアしたいと思います。
私は「要領の悪さ」と「どんくささ」でしたら、少なくともあなたには負けない自信があります!!
そんな私が、何故今まで自分は疑似言語が読めなかったのかを分析してまとめましたので、もしも参考に出来そうな所がありましたら、持って帰って下さい。

●混乱による理由
疑似言語の日本語によるプログラムの説明文でいろいろと難しそうな英字が出て来ますけれど、「それが変数なのか、配列なのか、プログラム(関数)名なのか」分からないと混乱します。
なので、配列の場合はhairetsu[]など、[]を書くことにしました。
また、どこを見ているのか分からなくなったので、左手でマウスを操作して、読んでいる所にカーソルを合わせ、右手でペンを持ってトレースする練習をしました。

●遅い
トレースが遅くて悩んでいました。それは配列の場合、どの要素番号なのか分からなくなってしまっていました。
そこで、例えばhairetsu[]={100,200,300,400,500}で配列の要素が0から始まる場合は、[0]と書いて、{100,200,300,400,500}の真上に0,1,2,3,4と配列の要素番号を書き、更にその右に「5」と配列の長さを書きました。
これにより解ける問題も出て来るかも知れません。
また、訓練によってトレースは早くなります。そこで、同じ過去問をじっくり解くという勉強を×3やりました。
そのプログラムを覚えてしまうぐらい繰り返してから次の過去問に行きました。
期間として1週間同じアルゴリズムを解きました。

●間違える
ミスを防ぐためには、変数の中でも関数が戻り値として返す変数に◯を囲いました。
私は引数、戻り値が良く分からなかったので、どこかで聞いたことのある例と対応付けました。カレーライスを作るプログラムが、処理の中でカレー鍋というプログラムを呼び出し、引数として(かっこ)の中に(じゃがいも、ニンジン、などなど)の具材を入れます。そこで戻り値として料理が出て来ます。
アルゴリズムが出来なかった頃の私は、カレー鍋の中に何の材料も入れないで、カレーライスを食べたい、何で出てこないの??あ、まちがってラーメン作っちゃった、という失態をしていました。

●テクニック
プログラムを読みやすくするテクニックとして、本文を良く読んで、何をやっているプログラムなのか日本語の説明文から掴む→
先に選択肢を見る→コメントとその対応のプログラムを見る→それからプログラム自体を見るという順番で解きました。

●CBTの画面上でのトレース
この本の読者特典に「動く疑似言語」といって、PowerPointを使った特典が付いています。


基本の整列、探索などのアルゴリズムの動きを画面上でトレース出来るので、令和2年度以降のCBT試験の対策として役立ちます。また本自体も解説が分かりやすいので、私はこの本でアルゴリズムのトレースを学びました。
若干扱っている年度が古いので、このあと紹介する比較的最近の過去問も合わせてやっておくと自信付くと思います。

●計算用紙でトレース
アルゴリズムを始めた頃はExcelで枠を作ってこの様に作っても良いと思います。

しかし、試験近くなって来たらA4用紙の中央に線を引いてその状態でこの様にトレースを出来るようなるまで練習あるのみです。

試験1週間前の元旦(令和3年1月1日)に解いたアルゴリズムです。

関連リンク:平成27年秋過去問ノート

関連リンク:平成29年春午後過去問ノート

●やっておくべき過去問3選
過去問どれからやるべきか迷う所です。そこでグズでノロマな私が無理なくアルゴリズム攻略出来るのに特に役立った過去問を3選紹介します。
※私の独断と偏見です。

第1位平成30年秋
このアルゴリズムは四則演算なので、+-×÷が分かればそれ以上の知識は要らずにトレース出来ます。なので、トレースのみに集中できて、すごくトレースの練習になります。
関連リンク:平成30年秋午後過去問ノート

第2位平成27年秋
このアルゴリズムは検索です。
配列の要素の比較をしてずらしながら検索して行きます。
こういった処理は基本情報技術者試験の良くあるパターンなのでこの試験の攻略するために練習になる問題です。

関連リンク:平成27年秋午後過去問ノート

第3位平成29年春
これはちょっと難易度が高いアルゴリズムですが、これを攻略出来たら自信もって良いと思います。経路探索、ダイクストラ法と呼ばれるアルゴリズムを使っています。
頭が混乱するかもしれませんが、アルゴリズムを攻略できたかどうかの要となる過去問だと私は思います。

関連リンク:平成29年春午後過去問ノート

最後にアルゴリズムの攻略や読んでいて面白いと思った本を紹介します。
すべて同じ著者、矢沢久雄先生の本です。(回し者では無く、良いものは良いと思ったので紹介致します。)

実際に作りながら学べますので、先の本と並行して学ぶと非常に面白いと思います。
javaとCに対応しています。(C言語はこの本のリンクからダウンロードで入手可能)

C言語なるほど実験室
基本情報技術者試験の範囲も扱っている実験を通して、プログラムの流れをつかめます。

関連記事

基本情報技術者試験トップ
アルゴリズム無料教材
CBT試験(午前免除午後試験)お役立ちリンク集
午前免除試験
これからプログラミングをはじめる方へ

基本情報技術者試験CBTお役立ちリンク集

基本情報技術者試験トップへ
これからプログラミングをはじめる方へ
風呂グラミング(入浴剤紹介)
息抜きに、写真で癒し(=^・^=)

2021年令和3年1月8日、基本情報技術者試験を受験しました。
午前免除済なので午後試験のみです。
試験問題の内容やそれを推測可能になる様な事は書けないので、
この記事では

●当日の持ち物
●計算用紙と筆記用具
●CBTとは
●FEのCBT
●コロナ対策
●試験会場(東京池袋)

について掲載します。


●当日の持ち物
CBT受験で入室、退室の時間の管理をしています。
その時にコロナ対策によりペンを借りることが出来ないので、
自分で持って行きます。
シャーペンとボールペン両方持って行ってどっちがいいか聞いた所、
「ボールペンの方が良い」と言われました。
また、時計は腕時計が苦手な方は、持って行かなくても大丈夫です。
CBTでは残り時間のカウンターが付いているので、
試験会場では使いませんでした。
会場まで時間通りに着けるようにスマホを持って行っただけで十分でした。

●計算用紙と筆記用具
計算用紙は1枚だけでした。なので、真ん中に線を引いて両面使いました。
字を小さく書く訓練をして当日に臨みました。
シャーペンも計算用紙と一緒に配布されました。
こう言ったら申し訳ないのですが、シャーペン、
ちょっと書きにくかったです。
グリップの所が持ちにくいな…と思いながら使っていました。
でも、回答はCBTだからマークシートではないので、
そこは大丈夫でした。



●CBTとは
私たち基本情報技術者試験を受ける方の前提知識として、
プロメトリック社のサイトのこのページのリンクを貼ります。

●FEのCBT
試験当日の受験の流れ

●コロナ対策
新型コロナウイルス情報

●試験会場(東京 西武池袋別館9F)
私が受けた試験は東京の池袋でした。
西武池袋本店別館9Fのパソコン教室、
池袋コミュニティ・カレッジ パソコン教室、
PCカレッジ 株式会社スーパーオフィスと言う所です。
地図

会場まではJR池袋駅の東口(南)を目安に41番出口から明治通りに出るので、
上記URLの地図の目印を探しながら「無印良品」まで行きました。
そこから、
「1階駐車場内エレベーター通路入り口」を歩いて行くと、
エレベータで9階に行けます。

基本情報技術者試験トップへ
これからプログラミングをはじめる方へ
風呂グラミング(入浴剤紹介)
息抜きに、写真で癒し(=^・^=)

平成29春の過去問問12 アセンブラ のプログラミング(コメント、トレースのノート付き)

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

この問題は乗算の応用です。ちょっと心配な方は駄菓子屋で5円チョコを買ったイメージで作ったサンプルプログラムをご覧下さい。
アセンブラCASL2で「2進数の乗算」を作ってみた

この問題は、2つの数を足すプログラムです。
0002と0003を加えたら0005になります。
Aに0002、Bに0003を設定して合計をAに入れて0005とします。
疑似言語風に書くと、「A←A+B」です。

設問1と2を一気に片付けるために、設問2の具体例を使ってプログラム1をトレースします。
AとBはともに64ビットなので、1語16ビットの為箱4つずつ使います。

A:「3F1D」「B759」「2E0C」「A684」
B: 「2E0C」「A684」「3F1D」「B759」
この加算結果がAに入ります。

では、実際にシミュレーターを使って実行していきます。

主記憶に2つの数AとBが入りました。

GR1にA+0、GR2にB+0のそれぞれのアドレスが入ってプログラム1のADD64を呼び出します。

演算に使うレジスタのGR0が初期化されました。

GR3にA+3、GR2にB+3が入りました。

桁上りのフラグに使うレジスタGR5が初期化されました。

GR0にAの3番地(最後の箱)の中身の数が入りました。

GR0にA+Bの3番地の演算結果が入りました。
OFが1になっているので、オーバーフローして、上の箱(上位桁)の演算結果に
加えます。

桁上りフラグが立ちました。…空欄「a」

演算結果がAの最後の箱に入りました。

桁上りの加算用にGR0に1が入りました。

GR3の「A+3」がGR1の「A+0」と比較されました。…空欄「b」
GR3の方が大きいのでSFは0です。

アドレスがデクリメントされ、GR3が「A+2」、GR4が「B+2」になりました。

LOOPに戻ります。・・・空欄「c」
この空欄ではアドレスがデクリメントされた「B+2」の状態について問われているので
それがマイナスになったりゼロになったりは無いので、単純分岐でJUMPです。

桁上りフラグが初期化されました。

GR0に先ほどの桁上り分の1に加えてA+2の「2E0C」が入ったので、
計算結果は「2E0D」です。…設問2の空欄「d」

あとは同じことの繰り返しなので、主記憶の演算結果のみを掲載します。

プログラミングです。

;平成29春64ビットの加算とそれを使った乗算
;メインプログラム
MAIN START
RPUSH
LAD GR1,A ;足し算に使う数Aの先頭アドレス
LAD GR2,B ;足し算に使う数Bの先頭アドレス
CALL ADD64
RPOP
RET
A DC #3F1D
DC #B759
DC #2E0C
DC #A684
B DC #2E0C
DC #A684
DC #3F1D
DC #B759


;プログラム1
ADD64
RPUSH
LD GR0,=0
LAD GR3,3,GR1 ;Aの一番後ろ4つ目
LAD GR4,3,GR2 ;Bの一番後ろ4つ目
LOOP1 LD GR5,=0 ;桁上りフラグ
ADDL GR0,0,GR3 ;Aを加算
JOV OV1 ;桁上りの分岐
JUMP NOV1 ;桁上りが無かった時
OV1 LD GR5,=1 ;空欄「a」桁上りフラグを立てる
NOV1 ADDL GR0,0,GR4 ;Bを加算
JOV OV2
JUMP NOV2
OV2 LD GR5,=1 ;空欄「a」
NOV2 ST GR0,0,GR3 ;加算結果をAへ格納
LD GR0,GR5 ;フラグを読み込んで次の加算へ
CPL GR3,GR1 ;空欄「b」全ての箱で処理が終わったか比較
JZE EXIT ;プログラムの修了へ分岐
SUBL GR3,=1 ;Aの加算対象を1つ上の箱にする
SUBL GR4,=1 ;Bの加算対象を1つ上の箱にする
JUMP LOOP1 ;空欄「c」アドレスの値はゼロやマイナスにならないから単純分岐
EXIT RPOP
RET
END

ここまでの流れをノートにまとめました。

設問3はプログラム1を使った足し算を呼び出してかけ算を行うプログラム2の問題です。32ビットのAとBという数の掛け算を行います。
乗算結果を64ビットのCに入れます。作業用に64ビットのTEMPという64ビットの領域を使います。それぞれの先頭アドレスを指すレジスタと演算に使う数値についてまとめました。

(GR1→)A:「0002」「0003」(以下0023)
(GR2→)B:「0004」「0005」
(GR3→)C:64ビットの空き領域
(GR7→)TEMP:64ビットの空き領域

プログラム2を動かして見ます。
(主記憶の状態を見やすいように、TEMPはメインプログラム内に書きました。)

A、B、C、TEMPが入りました。

GR1にA+0、GR2にB+0、GR3にC+0が入って、
プログラム2のMULT32を呼び出しました。

GR0にA+0に入っている0002が読み込まれました。

0002がTEMP+2に格納されました。

GR0にA+1に入っている0003が読み込まれました。

0003がTEMP+3に格納されました。

初期化に使う0が読み込まれました。

TEMPの上位ビットが0で初期化されました。

演算結果の入るCが0で初期化されました。

ループカウンタが読み込まれました。
カウンタであり、乗数をシフトするビットを表しています。

B+0が退避されました。

カウンタが退避されました。

16を引いたらマイナスになったので、乗数の下位語を読み込む処理に入ります。

乗数の下位の「0005」が読み込まれました。
0ビットシフトなので値は変わりません。

0005の最下位ビットは1なので、論理積を取って0001になりました。

C+0が読み込まれました。

TEMP+0が読み込まれました。
演算を行う領域の先頭アドレスが設定されたので、プログラム1のADD64を呼びます。
C :「0000」
TEMP:「0023」

プログラム1の加算処理は同じなので省略します。

C:「0023」つまり、「0023」×1

カウントアップされました。

GR1とGR2にTEMPの先頭アドレスを入れてプログラム1を使って加算処理をします。2倍になります。

TEMP:「0023」
TEMP:「0023」

TEMPが「0046」になりました。

つまり、「0023」×2^1です。
べき乗の1はカウンタと一致します。

プログラム2に戻り、B+0がGR2に戻りました。
ループまで戻りました。
GR6にGR5のカウンタ1が入り、16が引かれました。
1-16なのでまだマイナス、下位語の処理です。

乗数の5が読み込まれました。

1ビット右にシフトして0002になりました。

最下位ビットは0です。

カウントアップされました。
GR1、GR2にTEMPの先頭アドレスが読み込まれてプログラム1を呼びます。

TEMP:「0023」×2^1
TEMP:「0023」×2^1

の加算結果なので、

TEMP:「0023」×2^2が入って「4倍」されました。

プログラム2に戻り、GR2にB+0のアドレスが戻りました。
ループに戻ります。

乗数の「0005」が入りました。

乗数の「0005」を2ビットシフトして、「0001」になりました。
最下位ビットが1です。

GR1にC+0が読み込まれました。

GR2にTEMP+0が入りました。
これでプログラム1を呼ぶ準備が終わりましたので、プログラム1を呼びます。
C :「0023」×1
TEMP:「0023」×4
この加算で、

C:「0023」×5が入りました。
これで、Bの「0045」の「5」の乗算結果が入りました。

カウントアップされました。
GR1、GR2にTEMP+0が読み込まれてプログラム1の加算処理が行われます。

TEMP:「0023」×2^2
TEMP:「0023」×2^2

TEMP:「0023」×2^3
カウントが3なのでべき乗も3です。
つまり、16になると、「0023」×2^16で、「0230」になります。
ここまで進めます。

カウントが16になった時の主記憶です。

TEMPで「0023」が2^16倍されて「0230」になりました。

次から上位語の処理です。

16-16で0が入り、ここで初めてマイナスに分岐しなくなります。
つまり上位語を読み込みます。

Bの「0004」「0005」の「0004」が読み込まれました。
0ビットシフトで値は変わりません。

下位桁は0です。

カウントアップされました。
GR1とGR2にTEMPの先頭アドレスが設定されました。
プログラム1を呼びます。

TEMP:「0230」×2^0
TEMP:「0230」×2^0

TEMP:「0230」×2^1
ループに戻ります。

乗数をシフトするビット数です。

「0004」が読まれました。

1ビット右にシフトされました。

最下位ビットが0です。

カウンタが加算されました。
GR1とGR22TEMPのアドレスが読み込まれ、プログラム1を呼びます。

TEMP:「0230」×2^1
TEMP:「0230」×2^1

TEMP:「0230」×2^2(4倍)

ループに戻ります。
GR0に0004が読み込まれ、2ビットシフトして0001になり、
GR1にC+0、GR2にTEMP+0が読み込まれました。
C :「0023」×5倍
TEMP:「0230」×4倍
これで、「0023」×「0045」の演算が出来ました。


プログラム1は変わっていないので画像は省きます。


;平成29春64ビットの加算とそれを使った乗算
;メインプログラム
MAIN START
RPUSH
LAD GR1,A ;掛け算に使う数Aの先頭アドレス
LAD GR2,B ;掛け算に使う数Bの先頭アドレス
LAD GR3,C ;A×Bの結果領域
CALL MUL32
RPOP
RET
A DC #0002
DC #0003
B DC #0004
DC #0005
C DS 4
TEMP DS 4 ;演算結果を見やすくする為にメインプログラムへ移動

;プログラム2
MUL32
RPUSH
LAD GR7,TEMP ;初期化
LD GR0,0,GR1 ;GR1から始まる2語の領域の値を
ST GR0,2,GR7 ;TEMPから始まる4語の領域のうち
LD GR0,1,GR1 ;下位2語に格納
ST GR0,3,GR7
LD GR0,=0
ST GR0,0,GR7 ;TEMPから始まる4語の領域のうちの
ST GR0,1,GR7 ;上位2語に0を格納
ST GR0,0,GR3 ;GR3から始まる4語の領域に0を格納
ST GR0,1,GR3
ST GR0,2,GR3
ST GR0,3,GR3
LD GR5,=0 ;ループカウンタ
LD GR4,GR2 ;GR2の値をGR4に退避
LOOP2 LD GR6,GR5
SUBL GR6,=16 ;数Bの上位語か下位語か判断
JMI LOWORD ;空欄「e」32ビットのうちマイナスになるのは下位語
LD GR0,0,GR2 ;上位語の場合の処理
SRL GR0,0,GR6
JUMP TESTBIT
LOWORD LD GR0,1,GR2 ;下位語の場合の処理
SRL GR0,0,GR5
TESTBIT AND GR0,=#0001 ;最下位ビットが0か1か
JZE ELOOP
LD GR1,GR3 ;ADD64を呼ぶ準備で乗数の末尾が1の時
LAD GR2,TEMP
CALL ADD64
ELOOP CPL GR5,=31
JZE EXIT2
ADDL GR5,=1 ;カウントアップ
LAD GR1,TEMP ;ADD64を呼ぶ準備
LAD GR2,TEMP ;空欄「f」乗数の末尾が1の時も0の時も行う
CALL ADD64
LD GR2,GR4 ;GR4に退避した値をGR2に復帰
JUMP LOOP2
EXIT2 RPOP
RET

;プログラム1
ADD64
RPUSH
LD GR0,=0
LAD GR3,3,GR1 ;Aの一番後ろ4つ目
LAD GR4,3,GR2 ;Bの一番後ろ4つ目
LOOP1 LD GR5,=0 ;桁上りフラグ
ADDL GR0,0,GR3 ;Aを加算
JOV OV1 ;桁上りの分岐
JUMP NOV1 ;桁上りが無かった時
OV1 LD GR5,=1 ;空欄「a」桁上りフラグを立てる
NOV1 ADDL GR0,0,GR4 ;Bを加算
JOV OV2
JUMP NOV2
OV2 LD GR5,=1 ;空欄「a」
NOV2 ST GR0,0,GR3 ;加算結果をAへ格納
LD GR0,GR5 ;フラグを読み込んで次の加算へ
CPL GR3,GR1 ;空欄「b」全ての箱で処理が終わったか比較
JZE EXIT ;プログラムの修了へ分岐
SUBL GR3,=1 ;Aの加算対象を1つ上の箱にする
SUBL GR4,=1 ;Bの加算対象を1つ上の箱にする
JUMP LOOP1 ;空欄「c」アドレスの値はゼロやマイナスにならないから単純分岐
EXIT RPOP
RET
END

ご精読ありがとうございました。
平成21年春から平成30年秋までの20回分のうち、16回分のプログラミング及び
トレースが出来ました。
後は試験が終わったら残りの回のプログラミングとトレースをしながら試験結果を待ちたいと思います。

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

平成29秋の過去問問12 アセンブラ のプログラミング(コメント、トレースのノート付き)

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

この回の過去問は少し難しいというか、ややこしいと思います。なので、この記事をご覧になる前に、
平成21年秋過去問問12アセンブラ
平成25年春過去問問12アセンブラ

をご覧下さい。

この記事を更新している今現在は設問全て理解出来ましたが、理解するまでに手間取ってしまいました。
この問題苦手かも知れません。この記事でトレースしたり明日も問題を解いてみたりして、もう少し練習したいです。
試験が心配になってきた・・・。

ではこの問題について見ていきます。
1語16ビットで2語、つまり31ビット分のαという領域があります。
こんな感じです。
α+0「0011011000000000」
α+1「0000000000000000」
このαの一部がβという領域のビットと一致するところがあり、その位置を求めます。

β「11011」

α+0の2ビット目(先頭は0ビット)から5ビット分がβと一致します。
プログラム1「BSRH」では一致した位置の「2」がGR0に設定して呼び出し元に戻ります。

βはGR2に左詰めで「1101100000000000」と設定されます。
n=5ビット分の5はGR3に5、GR1はα+0を設定します。

ここまでの流れをノートにまとめました。

プログラミングする時は16進数で指定します。
α+0を16進数すると「3600」、α+1は「0000」、βは「D800」になります。
尚、シミュレータのレジスタの値は、2進数で表示します。

では、シミュレーターを使ってのトレースをします。

GR1にα+0の「アドレス」が、GR2にβ、GR3にビット数の5が設定されました。
プログラム1のBSRHを呼びます。

GR0に-1が入りました。αとβの一致するビットが見つからなかった時にGR0で-1を返します。
初期値として見つからなかった時の値が入りました。

GR6にマスク生成されます。
対象ビット以外をマスクする様にします。

対象の5ビット分右シフトされました。

マスクが反転されました。
これで、論理積を取ると対象の5ビット分以外が0になります。

GR4にα+0が入りました。

GR5にα+1が入りました。

GR1に2語分のビットの32が入りました。

GR1に32-5で27が入りました。

GR3に27が写されました。この差で一致するビットの位置を求めます。

GR7にGR4のα+0が写されました。

GR6のマスクと論理積を取って、最初の5ビットが取り出されました。
次に、GR2TO
GR7でGR2との排他的論理和を取ります。
もしも最初の5ビットが一致していたら0になります。・・・空欄「a」

0にならなかったので、一致しませんでした。

GR1が27から1を引いて26になりました。

GR4のα+0が左に1ビットシフトされました。
GR5のα+1も左に1ビットシフトされました。(0なので値変わらず)・・・空欄「b」

ループに戻ります。

GR7にα+0を左に1ビットした値が入りました。

GR6のマスクとの論理積で、GR7の先頭の5ビットが取り出されました。
GR7でGR2との排他的論理和を取ります。
もしも最初の5ビットが一致していたら0になります。

0にならなかったので、一致しませんでした。

26から1を引いて、25になりました。

GR4で、α+0を1ビット左シフトした値が更に1ビット左シフトされました。
GR5のα+1も左に1ビットシフトされました。(0なので値変わらず)

ループに戻ります。

GR4で、α+0が2ビット左シフトされた値がGR7に入ります。
GR6のマスクとの論理シフトされて先頭5ビットが取り出されました。
GR7でGR2との排他的論理和を取ります。
もしも最初の5ビットが一致していたら0になります。

GR2との排他的論理和で0になったので一致していました。
ラベルFOUNDに分岐します。

27-25で処理したビット分の2が求められました。

ビット位置2がGR0に入りました。

プログラムが終了しました。

;平成29年秋一致するビットを求めてその分置換する
;主プログラム
MAIN START
RPUSH
LAD GR1,ALPHA ;アドレスα+0を設定
LD GR2,BETA ;βを読み込む
LD GR3,N ;ビット数を読み込む
CALL BSRH ;プログラム1へ
RPOP
RET
ALPHA DC #3600 ;α+0
DC #0000 ;α+1
BETA DC #D800 ;β
N DC 5 ;ビット数


;プログラム1
BSRH RPUSH
LD GR0,=-1 ;初期値設定
LD GR6,=#FFFF ;マスク作成
SRL GR6,0,GR3 ;Nビット分だけ右シフト
XOR GR6,=#FFFF ;マスクのビットを反転
LD GR4,0,GR1 ;α+0の取り出し
LD GR5,1,GR1 ;α+1の取り出し
LD GR1,=32
SUBA GR1,GR3 ;GR1←32-n
LD GR3,GR1 ;GR3←32-n
LPH LD GR7,GR4 ;α+0の退避
AND GR7,GR6 ;マスクで対象部分を抜き出す
XOR GR7,GR2 ;空欄「a」結果が0なら一致
JZE FOUND ;一致あり
SUBA GR1,=1 ;処理済み分デクリメント
JMI FIN ;一致無し
SLL GR4,1 ;α+0を1ビット左シフト
SLL GR5,1 ;α+1も。オーバーフローしたらα+0へ
JOV NEXT ;空欄「b」↑の処理へ分岐
JUMP LPH
NEXT OR GR4,=#0001 ;2語目のオーバーフローした分
JUMP LPH
FOUND SUBA GR3,GR1 ;pの算出
LD GR0,GR3
FIN RPOP
RET
END

設問1が全て解答出来ました。

4行目:「1111111111111111」
5行目:「0000011111111111」
6行目:「1111100000000000」
で、対象ビットを取り出すマスクが出来ました。
これと同じ処理は、

「1000000000000000」これを、
「1111100000000000」にするので、
「算術シフト」を使います。先頭のビットが1なので、同じビットが入る算術シフトを
作る方法でもマスクが作れます。
-1してあるのでは、先頭の1の分があるのでその分引くからです。
この具体例ではマスクの1は1が5つになるようにします。つまり、
右4ビット「算術」シフトします。

もしも伝わりにくかったら、平成25年春アセンブラに詳細を書きましたので、
そちらをご覧下さい(=^・^=)m

では、設問3と4に行きます。
設問3は設問4の具体例を使うと、空欄「d」と設問4が一度に解けるので、その具体例を使います。

α+0「1111111111110011」
α+1「0111111111111111」
β  「11011」
n  「5」
γ  「11110」

この例ですと、1語目の後ろから2ビット(14ビット)~2語目の2ビット目までの5ビット間を置換します。

なので、実行後は
α+0「1111111111110011」(こっちは変わらず)
α+1「1101111111111111」(先頭から3ビット分変わっています)
になります。

ここまでの流れをノートにまとめました。

では、シミュレーターを動かしながらトレースをします。

主記憶の領域にα、β、n、γの所に問題文の値が設定されました。
実行後はα+0は変わりませんが、α+1が「DFFF」になります。
プログラム1のトレースの所は省略します。

αとβが一致するところが14ビット目なので、GR0に
14が求まります。それがGR2に入りました。

GR6でマスク生成されます。

右に5ビットシフトしました。

反転してマスクが完成しました。

対象のビット5が入りました。

1語のみなのか、1語と2語にまたがるのか、2語のみなのか判定するのに使うので、
16が入りました。

16から14を引いて2と求まりました。

GR3の2とGR7の対象ビット5が比較されました。
GR3の方が小さいので1語と2語にまたがります。

GR4のγがGR5に退避されました。

GR6のマスクがGR7に退避されました。

GR4が14ビットシフトされました。

GR6が14ビットシフトされました。

GR2にαの1語目が入りました。

マスクのGR6が反転されました。

GR6との論理積を取りました。

γの一部が足されて、1語目の置換処理が終了しました。

退避していたγがGR4に戻りました。

退避していたマスクがGR6に戻りました。

γが2語目の2ビット分GR4左シフトされました。

マスクも2ビットシフトされました・・・設問4の解答です(=^・^=)m

α+1のアドレスが入りました。

2語目が読み込まれました。

マスクが反転されました。

GR6のマスクとの論理積を取りました。

γの一部が足しこまれて置換が完了しました。・・・空欄「d」

2語目のα+1が主記憶に格納されました。

終了しました。

プログラムとノートです。


プログラム1の画像は省略しています。


;平成29年秋一致するビットを求めてその分置換する
;主プログラム
MAIN START
RPUSH
LAD GR1,ALPHA ;アドレスα+0を設定
LD GR2,BETA ;βを読み込む
LD GR3,N ;ビット数を読み込む
LD GR4,GAMMA ;γを読み込む
CALL BREP ;プログラム2へ
RPOP
RET
ALPHA DC #FFF3 ;α+0
DC #7FFF ;α+1
BETA DC #D800 ;β
N DC 5 ;ビット数
GAMMA DC #F000 ;γ


;プログラム2
BREP
RPUSH
CALL BSRH ;プログラム1を呼ぶ
LD GR2,GR0 ;一致したビットの位置が入る
JMI FIN
LD GR6,=#FFFF ;マスク生成
SRL GR6,0,GR3
XOR GR6,=#FFFF
LD GR7,GR3 ;GR7←n
LD GR3,=16
SUBA GR3,GR2 ;GR3←16-n
JMI ONL2 ;一致する部分ビット列が2語目だけのとき
JZE ONL2
CPA GR3,GR7 ;(16-p)とnの比較
JMI NEXTP ;2語にまたがる処理
JUMP ONL1 ;一致するビットが1語目だけのとき
NEXTP LD GR5,GR4 ;γを退避
LD GR7,GR6 ;マスクを退避
CALL S1
LD GR4,GR5
LD GR6,GR7
SLL GR4,0,GR3 ;2語目用γの調整
SLL GR6,0,GR3 ;2語目用マスクの調整
LAD GR1,1,GR1
CALL S2 ;2語目の最終処理
JUMP FINP
ONL1 CALL S1
JUMP FINP
ONL2 LD GR2,=0 ;空欄「c」シフトするビット数
SUBA GR2,GR3 ;GR2←p-16
LAD GR1,1,GR1 ;操作対象を2語目にして、
CALL S1 ;2語目の処理
FINP RPOP
RET
S1 SRL GR4,0,GR2 ;γの調整
SRL GR6,0,GR2 ;マスクの調整
S2 LD GR2,0,GR1 ;操作対象後の取り出し
XOR GR6,=#FFFF
AND GR2,GR6
OR GR2,GR4 ;空欄「d」で置換処理
ST GR2,0,GR1
RET
;プログラム1
BSRH RPUSH
LD GR0,=-1 ;初期値設定
LD GR6,=#FFFF ;マスク作成
SRL GR6,0,GR3 ;Nビット分だけ右シフト
XOR GR6,=#FFFF ;マスクのビットを反転
LD GR4,0,GR1 ;α+0の取り出し
LD GR5,1,GR1 ;α+1の取り出し
LD GR1,=32
SUBA GR1,GR3 ;GR1←32-n
LD GR3,GR1 ;GR3←32-n
LPH LD GR7,GR4 ;α+0の退避
AND GR7,GR6 ;マスクで対象部分を抜き出す
XOR GR7,GR2 ;空欄「a」結果が0なら一致
JZE FOUND ;一致あり
SUBA GR1,=1 ;処理済み分デクリメント
JMI FIN ;一致無し
SLL GR4,1 ;α+0を1ビット左シフト
SLL GR5,1 ;α+1も。オーバーフローしたらα+0へ
JOV NEXT ;空欄「b」↑の処理へ分岐
JUMP LPH
NEXT OR GR4,=#0001 ;2語目のオーバーフローした分
JUMP LPH
FOUND SUBA GR3,GR1 ;pの算出
LD GR0,GR3
FIN RPOP
RET
END

空欄「c」を埋めるのに2語目のみ置換対象となる具体例を考えましたので、それで
トレースをします。

α+0「0000000000000000」
α+1「0110110000000000」
β  「11011」
n 「3」
γ  「11111」

主プログラムのここの所のみを変えました。

空欄cのある所とその少し後までトレースをします。
2語目の1ビットなので、17を返してレジスタに移された所から始めます。

GR2に17が入りました。

GR6にマスクが作成されました。

対象のビットが入りました。

1語目のみ、2語目のみ、1、2語にまたがるを判定するのに使う16が入りました。

16-17で-1になり、2語目のみと判定されました。

GR2がゼロクリアされました。・・・空欄「c」
これは後でマスクをシフトするビットを求めるのに使います。

0-(-1)で1が求まりましたので1ビットシフトするのに使います。

以下略

ここまでの流れをノートにまとめました。

お疲れ様でした。

今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)
要領悪すぎにゃ~~~~~~( ;∀;)(=^・^=)( ;∀;) (^O^)/

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

平成30春の過去問問12 アセンブラ のプログラミング(コメント、トレースのノート付き)

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

この問題は平成26春のアセンブラの問題に似ています。
また、自作の2進数の乗算プログラムもあります。

この記事は、この記事は基本情報技術者試験の選択言語でアセンブラ言語を選んだ方と、似顔絵に興味のある方でしたら、ちょっとした暇つぶしになるのかもしれません。え、暇なんて無い???そんなぁ、ちょっとだけ見て行ってよ( ;∀;)(途中途中に、似顔絵が登場します。)

平成30年春のアセンブラの問題は、これもアセンブラ色が強いと思いました。
数字列を数値に変換して、管理テーブルと呼ばれるテーブルに格納して、それをかけ算するといった処理を行います。かけ算の仕方は頻出だと思うので(特に乗数の下一桁が0かどうかとか)真剣に書きたいと思います。

ではまず、数字列を数値に変換するプログラム1に入ります。
この具体例はそのまま使えると思います。

数字列「567」を数値にするとは、文字コード「0035」を数値の5である「0005」に変換して、数値なので演算をして100倍、文字コード「0036」を数値の6に変換して10倍、文字コード「0037」を数値の7に変換して合計して数値の「567」にします。

この時、10倍のやり方について少し見てみます。
例えば5を10倍すると50になりますが、まず5を2倍した10と、その10をどっかに退避して、退避した分を2倍すると20、更に2倍すると40(元の数5の8倍)となり、
それを元の数を2倍した10の所にこの40を足すと50になります。

この、まず2倍にして、2倍にした数を退避して、
退避した数を4倍すると元の数の8倍になり、元の数の2倍と足しこんで結果10倍にするというやり方も、
アセンブラ色が強い、かなり有力なパターンなのではと思いました。

プログラム1を呼び出すメインプログラムに、数字列の入った領域の先頭のアドレスを指定します。数字列の入った領域の名前は「SUUJI」とします。GR1が「SUUJI+0」を指します。「SUUJI+0」に数字5の文字コード0035、「SUUJI+1」に数字6の文字コード0036、「SUUJI+2」に数字7の文字コードが入っています。
また、文字数はこの具体例の倍は3文字なので、3をGR2に読み込みます。
戻り値である567はGR0に読み込んでメインプログラムに戻ります。

ここまでの内容をノートにまとめました。

実際に数字列「567」を数値「567」に変換するプログラムを過去問を参考にして作ってシミュレーターで動かしてみます。

主記憶に数字列「567」が入りました。数字列SUUJIの「5」が入っている所の先頭アドレスは「SUUJI+0」です。うちの環境では101Cになっています。

GR1にSUUJIの先頭アドレスが入って、GR2に文字数が入りました。

GR2にSUUJIのアドレスに文字数の3が加算され、「SUUJI+3」になりました。

数字列を数値に変換した数(戻り値)を格納するGR0を初期化しました。

GR1の「SUUJI+0」はGR2の「SUUJI+3」よりも小さいので、SFが1になりましたので、まだ変換処理が終わっていないです。

GR4に数字列の「5」が読み込まれました。

数値の「5」に変換されました。
GR0の0が10倍されます。ここは値が変わらないので、このループでは略して、
次からトレースします。

戻り値に使うレジスタGR0に数値の「5」が格納されました。

GR1のアドレスが「SUUJI+1」になりました。
ループに戻ります。

GR1は「SUUJI+1」とGR2の「SUUJI+3」よりも小さいのでSFが1です。
まだ処理をします。

GR4に数字列の「6」が読み込まれました。

GR4の所が数値の「6」になりました。

GR0の所で、さっき処理した「5」が2倍され「10」(A)になりました。

10がGR5に退避されました。

10が4倍されて40になりました。(28は2×16+8)

5の2倍と5の8倍が足されて50になりました。
(32は3×16+2)

今数値に変換された6が足されました。

GR1が指している先が「SUUJI+2」になりました。

GR1の「SUUJI+2」はGR2の「SUUJI+3」より小さいのでSFが1になり処理中です。

GR4に数字列の「7」が読み込まれました。

数値の「7」に変換されました。

GR0が2倍されました。

2倍された数が退避されました。

2倍された数が4倍され、8倍になりました。

2倍された数に8倍された数が足されて10倍になりました。

ここに今数値に変換された7が足しこまれました。
これで567になったのですが、表示を10進数に切り替えて見てみます。

10進数表示で567になりました。
GR1のアドレスが「SUUJI+3」になり、ループに戻ります。
(表示を16進数に戻しました。)


GR1もGR2も「SUUJI+3」になったので、ZFが1になりました。

終了しました。
お疲れ様です。

主プログラムとプログラム1のプログラミングとノートを掲載します。

;平成30春 数字列を数値に変換して管理テーブルに格納してかけ算するプログラム
;メインプログラム
MAIN START
RPUSH
LAD GR1,SUUJI
LD GR2,=3
CALL DTOB
RPOP
RET
SUUJI DC ‘567’


;プログラム1
DTOB RPUSH
ADDL GR2,GR1 ;アドレスを文字数分だけ進めて終了条件の判定に使う
LAD GR0,0 ;戻り値の初期化
LPDT CPL GR1,GR2 ;変換終了?
JZE FINDT
LD GR4,0,GR1 ;数字1文字の取り出し
SUBL GR4,=’0′ ;1桁を数値に変換
SLL GR0,1 ;GR0を10倍してGR4を加算。まずここで2倍
LD GR5,GR0 ;2倍した数を退避
SLL GR5,2 ;空欄「a」退避した数を4倍(元の数の8倍)
ADDL GR0,GR5 ;8倍した結果を2倍した数に足しこむ
ADDL GR0,GR4 ;読み込んだ数値を足す
LAD GR1,1,GR1 ;次の数値を読み込むので1つ進める
JUMP LPDT ;ループへ
FINDT RPOP
RET
END

プログラム2のGETWDでは、さっきのDTOBを使って数字列を数値に変換したらそれを管理テーブルと呼ばれる保存領域に格納します。管理テーブルの領域を「KANRI+0」にします。

まんまじゃん。

JAROのマギラワシ編

GETWDでは、SUUJIの数字列の具体例は問題より一部簡略化して(オーバーフローを防ぐため)数字列SUUJI「△△1234△567△△△9876△.」をプログラム1のDTOBを使って数値に変換して、その際に空白文字△で区切って数値に変換します。
管理テーブルKANRIのKANRI+0、KANRI+1、KANRI+2‥‥と格納していきます。
KANRIの大きさは仮に4、つまりKANRI+3までとします。

さっきと同じようにGR1でSUUJI+0を、GR2でKANRI+0を指して、DTOBを呼ぶのに文字数を求める必要があるので、計算の為にGR1、GR2のアドレスをGR6、GR7に退避してアドレスの差から文字数を求めます。
それが求まったらDTOBを呼びます。数値に変換した後にGETWDに戻ります。
KANRIのアドレスを1つ先に進めて、変換及び格納処理に戻ります。
最後に「.」の時に「-1」を格納して終了の目印にします。

ここまでの流れをノートにまとめました。

このプログラム2の名前、GETWDで、TM NETWORKさんの『Get Wild』のサビが浮かんできました。
同じような人いるかな??

では、プログラミングしてトレースします。

数字列SUUJI「△△1234△567△△△9876△.」が主記憶に読まれました。
先頭のアドレス「SUUJI+0」はうちの環境では101Cになっています。

管理テーブルKANRIの領域が確保されました。
先頭アドレス「KANRI+0」はうちの環境では102Fになります。

SUUJI+0とKANRI+0をセットしてGETWDを呼びます。

SUUJI+0をGR6、KANRI+0をGR7に退避しました。

処理状態のフラグが初期化されました。

位置調整の為にSUUJI-1になりました。

SUUJI+0になりました。
0番目の数字の処理になるのでインデックスと一致します。

GR4にSUUJI+0番目の「△」が読まれました。
何もせずに次に行きます。
次のSUUJI+1も「△」なので何もせずに次に行きます。

SUUJI+2は「1」です。

処理中フラグが0になりました。

GR1にSUUJI+2が退避されました。

GR4にSUUJI+3の数字列2が読まれました。

GR4にSUUJI+4の数字列3が読まれました。

GR4にSUUJI+5の数字列4が読まれました。

GR4にSUUJI+6の数字列△が読まれました。
空白なので格納処理に移ります。

GR2にSUUJI+6が格納されました。

GR2にアドレスの差から「SUUJI+6」-「SUUJI+2」で4文字と求められました。
これでGR1に「1234」の先頭の「SUUJI+2」、GR2に文字数の「4」が入ったので、プログラム1のDTOBを呼ぶ設定が完了しました。
DTOBを呼びました。数字列「1234」を数値の「1234」に変換します。
処理はプログラム1と同じなので省略して、GETWDに戻った所からトレースします。

10進数に直すと1234にあたる04D2がGR0に格納されました。

主記憶の管理テーブルのKANRI+0に格納されました。

数字列の処理中フラグが解除されました。

あと同様に「△△1234△567△△△9876△.」の567~進めて、
最後の「.」で終了処理の「-1」を格納します。
結果のみを表示します。

このようになりました。
表示は10進数表示にしました。

終了しました。お疲れ様です。
では、プログラムとノートです。

まいう~~~

プログラム1は同じなので画像は省略します。

;平成30春 数字列を数値に変換して管理テーブルに格納してかけ算するプログラム
;メインプログラム
MAIN START
RPUSH
LAD GR1,SUUJI ;数字列の先頭アドレス
LAD GR2,KANRI ;管理テーブルの先頭アドレス
CALL GETWD
RPOP
RET
SUUJI DC ‘ 1234 567 9876 .’ ;数字列
KANRI DS 4 ;管理テーブル


;プログラム2
GETWD
RPUSH
LD GR6,GR1 ;数字列の先頭アドレスを退避
LD GR7,GR2 ;管理テーブルの先頭アドレスを退避
LD GR3,=-1 ;数字列の処理状態フラグの初期化
LAD GR6,-1,GR6 ;ループ前の数字列を指す位置調整
LPGE LAD GR6,1,GR6 ;処理中の数字列の位置
LD GR4,0,GR6 ;1文字取り出し
CPL GR4,=’.’ ;ピリオドですか?
JZE FINGE
CPL GR4,=’ ‘ ;空白ですか?
JNZ NUM ;空欄「b」処理中のフラグのチェック
CALL SETWD ;管理テーブルに格納する処理
JUMP LPGE
NUM LD GR3,GR3 ;数字列の処理中?
JZE LPGE
LD GR3,=0 ;数字列の処理中フラグの設定
LD GR1,GR6 ;数字列の先頭アドレスを退避
JUMP LPGE
FINGE CALL SETWD
LD GR2,=-1 ;終了の目印
ST GR2,0,GR7 ;↑数値の終わりを示す印を格納
RPOP
RET
SETWD LD GR3,GR3 ;0(=処理中)ですか?
JNZ FIN2 ;空欄「c」違ったら何もせずに戻る
LD GR2,GR6 ;処理をしていた位置を読み込む
SUBL GR2,GR1 ;位置の差から文字数を求める
CALL DTOB ;数字列を数値に変換
ST GR0,0,GR7 ;数値を管理テーブルに格納する
LD GR3,=-1 ;数字列の処理中状態を解除
LAD GR7,1,GR7 ;空欄「d」管理テーブルを1つ先に進める
FIN2 RET

;プログラム1
DTOB RPUSH
ADDL GR2,GR1 ;アドレスを文字数分だけ進めて終了条件の判定に使う
LAD GR0,0 ;戻り値の初期化
LPDT CPL GR1,GR2 ;変換終了?
JZE FINDT
LD GR4,0,GR1 ;数字1文字の取り出し
SUBL GR4,=’0′ ;1桁を数値に変換
SLL GR0,1 ;GR0を10倍してGR4を加算。まずここで2倍
LD GR5,GR0 ;2倍した数を退避
SLL GR5,2 ;空欄「a」退避した数を4倍(元の数の8倍)
ADDL GR0,GR5 ;8倍した結果を2倍した数に足しこむ
ADDL GR0,GR4 ;読み込んだ数値を足す
LAD GR1,1,GR1 ;次の数値を読み込むので1つ進める
JUMP LPDT ;ループへ
FINDT RPOP
RET
END

プログラム3MULTは掛け算をします。具体例として、数字列「2△3.」からプログラム1のDTOBを使って数字列から数字に「2」と変換して、GETWDを使って管理テーブルCTBL+0に格納して次に「3」も同様にしてCTBL+1に格納します。それをMUTに戻ってかけ算をします。

では、数字列「2△3.」を数値「2」と「3」変換する所までのトレースはプログラム1と2と同じなので省略して、メインのかけ算プログラムのトレースを重点的に行います。

ここまでの流れをノートにまとめました。

管理テーブルに数値に変換して格納されました。
ここからはレジスタを2進数表示にしてトレースします。

GR4に被乗数の「…0010」、GR5に乗数の「…0011」が入りました。

GR0が初期化されました。

乗数は0では無いのでZFは0です。

最下位ビットを調べるので退避しました。

0001と論理積を取って最下位ビットを調べました。
0??  ち、が、う、だ、ろ!!

なので、加算処理を行います。

「2」が入りました。

被乗数が「2」が左に1ビット論理シフトして「4」になりました。

乗数「3」が右に1ビット論理シフトして「1」になりました。

乗数1は最下位ビットが「1」なので、加算処理を行います。

GR4の「4」がGR0の「2」と加算されて「6」になりました。

GR4が1ビット左に論理シフトされて2倍されました。

GR5が1ビット右に論理シフトされて「0」になりました。
計算は終了して呼び出し元のメインプログラムに戻ります。

プログラムが終了しました。

お疲れ様でした。

プログラム3とノートです。

画像はプログラム1、2は共通なので省略します。

;平成30春 数字列を数値に変換して管理テーブルに格納してかけ算するプログラム
;メインプログラム


MAIN START
RPUSH
LAD GR1,SUUJI ;数字列の先頭アドレス
CALL MULT
RPOP
RET
SUUJI DC ‘2 3.’ ;数字列


;プログラム3
MULT
RPUSH
LAD GR2,CTBL ;管理テーブルの先頭アドレスを読み込む
CALL GETWD ;数値を管理テーブルに格納する処理
LD GR4,0,GR2 ;GR4←被乗数
LD GR5,1,GR2 ;GR5←乗数
LD GR0,=0 ;計算結果を初期化
LD GR5,GR5 ;乗数はゼロか?
LPMU JZE FINMU ;空欄「e」
LD GR3,GR5 ;乗数を退避
AND GR3,=#0001 ;乗数の最下位ビットのチェック
JZE NEXTMU ;↑ゼロだったら加算処理をスキップ
ADDL GR0,GR4 ;被乗数を結果に加算
NEXTMU SLL GR4,1 ;被乗数を1ビット左論理シフト
SRL GR5,1 ;空欄「f」乗数を1ビット右論理シフト
JUMP LPMU
FINMU RPOP
RET
CTBL DS 3 ;GETWD用管理テーブル

;プログラム2
GETWD
RPUSH
LD GR6,GR1 ;数字列の先頭アドレスを退避
LD GR7,GR2 ;管理テーブルの先頭アドレスを退避
LD GR3,=-1 ;数字列の処理状態フラグの初期化
LAD GR6,-1,GR6 ;ループ前の数字列を指す位置調整
LPGE LAD GR6,1,GR6 ;処理中の数字列の位置
LD GR4,0,GR6 ;1文字取り出し
CPL GR4,=’.’ ;ピリオドですか?
JZE FINGE
CPL GR4,=’ ‘ ;空白ですか?
JNZ NUM ;空欄「b」処理中のフラグのチェック
CALL SETWD ;管理テーブルに格納する処理
JUMP LPGE
NUM LD GR3,GR3 ;数字列の処理中?
JZE LPGE
LD GR3,=0 ;数字列の処理中フラグの設定
LD GR1,GR6 ;数字列の先頭アドレスを退避
JUMP LPGE
FINGE CALL SETWD
LD GR2,=-1 ;終了の目印
ST GR2,0,GR7 ;↑数値の終わりを示す印を格納
RPOP
RET
SETWD LD GR3,GR3 ;0(=処理中)ですか?
JNZ FIN2 ;空欄「c」違ったら何もせずに戻る
LD GR2,GR6 ;処理をしていた位置を読み込む
SUBL GR2,GR1 ;位置の差から文字数を求める
CALL DTOB ;数字列を数値に変換
ST GR0,0,GR7 ;数値を管理テーブルに格納する
LD GR3,=-1 ;数字列の処理中状態を解除
LAD GR7,1,GR7 ;空欄「d」管理テーブルを1つ先に進める
FIN2 RET

;プログラム1
DTOB RPUSH
ADDL GR2,GR1 ;アドレスを文字数分だけ進めて終了条件の判定に使う
LAD GR0,0 ;戻り値の初期化
LPDT CPL GR1,GR2 ;変換終了?
JZE FINDT
LD GR4,0,GR1 ;数字1文字の取り出し
SUBL GR4,=’0′ ;1桁を数値に変換
SLL GR0,1 ;GR0を10倍してGR4を加算。まずここで2倍
LD GR5,GR0 ;2倍した数を退避
SLL GR5,2 ;空欄「a」退避した数を4倍(元の数の8倍)
ADDL GR0,GR5 ;8倍した結果を2倍した数に足しこむ
ADDL GR0,GR4 ;読み込んだ数値を足す
LAD GR1,1,GR1 ;次の数値を読み込むので1つ進める
JUMP LPDT ;ループへ
FINDT RPOP
RET
END

今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
以前書き貯めて置いた(トレース中の落書き…)似顔絵イラストを入れて、遊び心を取り入れたりしたので、ウケなかったり、誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)
要領悪すぎにゃ~~~~~~( ;∀;)(=^・^=)( ;∀;) (^O^)/

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

この問題は平成26春のアセンブラの問題に似ています。
また、自作の2進数の乗算プログラムもあります。

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

平成30秋の過去問問12 アセンブラ のプログラミング(コメント、トレースのノート付き)

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです
関連記事:自作サンプルプログラム「うるう年の判定」

この記事は基本情報技術者試験の選択言語でアセンブラ言語を選んだ方と、芸能人の椿鬼奴さんに興味のある方でしたら、ちょっとした暇つぶしになるのかもしれません。え、暇なんて無い???そんなぁ、ちょっとだけ見て行ってよ( ;∀;)

この問題、うるう年の判定があるので、アルゴリズムの基礎からキッチリやっておいてよかったなぁと思います。
うるう年のアルゴリズムは、この本のが分かりやすいです。

1970年1月1日を基準の日として日数を計算するプログラムです。これは具体例を用意しないと、なかなか難しいなと思いました。それで、どうやって具体例の日付を考えたかと申しますと、計算が簡単そうで尚且つ、うるう年だとプログラミングの練習になると思ったので、1972年にしました。その中でもうるう年では2月29日まであるので、3月以降の日付にした方が練習になりそうです。
1972年3月生まれ以降の芸能人の方の生年月日を見てみた所、椿鬼奴(つばきおにやっこ)さんの1972年4月15日があったので、この日付をこの問題の具体例にしようかなと決めました。

まず、メインプログラムMAINで椿鬼奴さんの生年月日を設定します。
配列を誕生日だからBIRTHとして、BIRTH+0に1972年、BIRTH+1に4月、BIRTH+2に15日を入れます。それからプログラム1のDAYOFFSTを呼び出します。
それで、日数をカウントするのにうるう年かどうか調べる必要があるので、プログラム2のLEAPYEARを呼び出して、更に4、100、400で割りきれるか調べるのに使う割り算プログラムDIVISIBLを使います。
DIVISIBLはコード省略なので、引き算を利用して自作しました。

では、トレースしていきます。日付の数値が大きいのと計算を分かりやすくする為に、
10進数でトレースしました。

ここまでの流れをノートにまとめました。

主プログラムが呼び出され、主記憶に「1972」、「4」、「15」が入りました。
この生年月日の入った配列BIRTHの先頭アドレスをGR2で指し示しました。
ここから副プログラム1のDAYOFFSTを呼びます。

年、月、日が各レジスタに入りました。

1日からの日数を求めるので、1が引かれました。

配列ACCMDAYSに1月1日からの平年の日数が入っていますので、これを使って1972内の日数計算を行います。
1972年1月1日から同年4月15日までですが、1月の「31日」分と、2月の「28日」分と、3月の「31日」分を足した90をGR1の14に加えるために、GR3の4月の「4」を使って配列のインデックスを指し示します。
配列の先頭は0から始まるので、そのまま足すと5月になり、まずその位置を指定します。空欄「a」の下にGR4とあるので、このGR4に何かするみたいですね。
GR4に配列ACCMDAYSのインデックスを指し示すようにしたいので、「LAD GR4,ACCMDAYS,GR3」が入ります。
このまま足すと5月の日数になってしまうので、1つ前にずらして3番目の(しつこいようですが、この問題での配列のインデックスは0~始まります。)
「90」をGR1に足しこみます。
GR1に元々あった14に90が足されて、104になりました。

次に、この足しこんだ日数は「平年の」場合です。うるう年でしたら3月以降は1を足します。なので、GR3の月が3月より小さかったらSKIPに分岐して、そうではなかったら1972年がうるう年かどうか調べる必要が出て来ます。
この図から分かるように、4月なのでSFも0になったので、1972年がうるう年かどうか調べます。

副プログラムを呼び出す前に、GR2に年を入れました。
CALLでLEAPYEARが呼び出されました。

うるう年かどうかのフラグをGR0に設定する為にゼロクリアしました。

まず、4で割れるか調べるので、GR3に年を入れました。

0なので、1972は4で割れました。
調べるために、3(…0011)と論理積を取ります。1余る場合は0001、2余る場合は0010、3余る場合は0011となり、0になりません。なので、0にならなかった時の分岐に使います。空欄「c」は「JNZ FIN」
1972は3と論理積を取って0になったので、4で割れます。なので、うるう年の「可能性」があります。4で割れて更に100で割れなければ過去問62ページの(2)②の条件に該当するのでうるう年になります。では、100で割れるかどうか調べるために割り算プログラムのDIVISIBLを使います。これはコードが省略されていたので、引き算を利用して調べられるように自作しました。

DIVISIBLを呼ぶ前にGR3に100が入りました。
1972から100を引いて行って、0より大きかったら(JPL)引き算LOOPDに分岐、0になったら割れるからWARERUに分岐、そうでなければマイナスになるので分岐せずに割り切れない処理を行います。では、DIVISIBLを呼びます。

100ずつ引いて行って、72が残りました。
まだプラスなのでLOOPDに分岐します。

マイナスになりました。

割り切れなかったので、GR0に0が入りました。
呼び出し元のLEAPYEARに戻りました。
ここまでで、4で割り切れて100で割り切れないことが分かったので、うるう年決定です。

うるう年の場合はGR0に1を設定しますので、反転する処理を行います。
空欄「d」は「XOR GR0=,=1」です。呼び出し元のDAYOFFSTに戻りました。

このGR0の1が、日数の入っているGR1の104に加わって105になります。
これで、1972年分の日数は105と求まったので、次に1970年、1971年の分を行います。

まずは1970年からうるう年かどうか調べるのでGR2に入りました。

GR2の1970がGR5の1972と比較されます。
GR2の方が小さいので、SFが1になりました。
1970年と1971年の日数加算処理を行いたいということは、1972と等しかったら日数加算処理が終了だから終了のBREAKに分岐します。なので、空欄「b」は「JZE BREAK」です。では、LEAPYEARを読んで、1970年がうるう年かどうか調べます。

3(…0011)との論理演算の結果、2(…0010)となったので、うるう年ではなく「平年」であることが決定しました。呼び出し元に戻ります。

平年なので、365をGR1に元々入っていた105に加えます。

470になりました。

次に1971年がうるう年かどうか調べるので、年数が1加算されました。

GR2の1971とGR5の1972が比較され、GR2の方が小さいので、SFが1になりました。
LEAPYEARが呼ばれました。

4で割ったあまりが3になったので、割り切れないで平年確定です。
呼び出し元に戻りました。

平年だから365が加算され、もともとあった470に加わって835になりました。

年が1つ加算されて、1972年になりました。

GR2、GR5と比較して、どっちも1972で等しいので、ZFが0になりました。
これで日数加算処理は終わります。

プログラムを終了しました。

次に設問2に入ります。オーバーフローの場合ですよね。オーバーフローするとOFが1になります。なので、オーバーフローの分岐になるので、空欄「f」は「JOV」です。

空欄「e」は、オーバーフローするのは日数なので、日数が加算されるレジスタはGR1であることから、19行目になります。

最後にプログラムとノートです。

;平成30秋日数を求めるプログラム
;主プログラム及び副プログラム群
;これは自作の主プログラム
MAIN START
RPUSH
LAD GR2,BIRTH
CALL DAYOFFST
RPOP
RET
BIRTH DC 1972 ;椿鬼奴(つばきおにやっこ)さんの生年月日
DC 4
DC 15


;プログラム1
DAYOFFST
RPUSH
LD GR5,0,GR2 ;GR5 :年
LD GR3,1,GR2 ;GR3 :月
LD GR1,2,GR2 ;GR1 :日
SUBL GR1,=1 ;GR1で日数をカウント
LAD GR4,ACCMDAYS,GR3 ;空欄「a」月をインデックスとして指し示す
ADDL GR1,-1,GR4 ;1月1日からの日数(平年)を求める
CPA GR3,=3 ;月が3月以降のときうるう年を考慮
JMI SKIP ;1月と2月だったらスキップ
LD GR2,GR5 ;年を読み込んで、
CALL LEAPYEAR ;うるう年かどうか調べる
ADDL GR1,GR0 ;副プログラムから戻ってGR0の値を加算
SKIP LD GR2,=1970 ;1970年から(年-1)年までの間(ただし、
LOOP CPA GR2,GR5 ;年>1970)、1年の日数を加算
JZE BREAK ;空欄「b」1970年または年の日数加算が終わったら終了
CALL LEAPYEAR ;1970年、1971年…具体例の年の1年前まで
ADDL GR0,=365 ;GR0の0または1に365を加算
ADDL GR1,GR0 ;日数加算
ADDA GR2,=1 ;年を1970年~具体例の年まで進める
JUMP LOOP
BREAK LD GR0,GR1 ;日付をGR0に設定して主プログラムに戻る
EXIT RPOP
RET
;ACCMDAYSは、平年の各月1日の1月1日からの日数(1月1日は0日目)
ACCMDAYS DC 0,31,59,90,120,151,181,212,243,273,304,334

;プログラム2
LEAPYEAR
RPUSH
SUBA GR0,GR0 ;ゼロクリア
LD GR3,GR2 ;年を設定
AND GR3,=3 ;…0011と論理積
JNZ FIN ;空欄「c」論理積が0出ないなら4で割り切れていない→平年
LD GR3,=100 ;4で割れたら100でも割れるか調べる
CALL DIVISIBL ;割り算プログラムを呼ぶ
XOR GR0,=1 ;空欄「d」で100で割れ無かったらうるう年確定で呼び出し元に戻る
JNZ FIN
LD GR3,=400 ;100で割れた年は、400でも割れるか調べる
CALL DIVISIBL
FIN
RPOP
RET
;これは自作の割り算副プログラム
DIVISIBL
RPUSH
LOOPD SUBL GR2,GR3
JPL LOOPD
JZE WARERU
LD GR0,=0
JUMP FIND
WARERU
LD GR0,=1
FIND
RPOP
RET
END

<<のーと3、4、5>>

今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
頑張って書いたので、誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)
要領悪すぎにゃ~~~~~~( ;∀;)(=^・^=)( ;∀;) (^O^)/

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです
関連記事:自作サンプルプログラム「うるう年の判定」

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)