的 86 マシン眺伝の書
mmmm
咖 li マシン瞧書
イラスト ㊃眞島真太郎
はじめに
コンピュータ言語にも色々なものがありますが、ひとつだけすべてに共通し
ていることがあります。それは、最終的には必ずマシン語になって、あるいは
マシン語によって動いているという事実です。
フランス語、英語、スペイン語、日本語……。言葉に種類があるように、マ
シン語にもいくつかの種類があります。通常、ニモニックによるアセンブリ言
語もマシン語といいますが、 Z 80、 8080、8086, 6502、6809、80286、80386……
など、 CPU の違いによってマシン語 (ニモニック) はバラバラです。さらに、
人間の言葉に方言があるように、マシン語にはハードウェアの違いという方言
以上に面倒な壁が存在しています。
そのため、同じ CPU を搭載したコンピュータでも、実際の用法は機種によっ
てまったく違うものとなります。その結果、 CPU 別にマシン語の解説をしよう
とすると、どうしてもニモニックそのものの解説が中心になりがちです。また、
機種別にマシン語を解説しようとすると、今度はハードウェア•コントロール
に関する説明が必須となり、プログラムは急激に現実味を帯びたものになって
しまいます。
そもそも、マシン語というものは複数の命令によって意味をなす言語ですか
ら、ニモニックは単なるアルファベット的な存在にすぎません。したがって、
本来ならば基本的なアルゴリズムや基礎テクニックをマスターしてから、現実
的なプログラムへと進むべきものです。しかし、それではマシン語に対する興
味を持続することが困難となるので、とりあえずゲームなど楽しいことを目標
にマシン語を覚えるわけです。
そこで、たとえ順序は逆であっても、ある程度マシン語をマスターしたなら、
改めてゆっくりと基礎テクニックを振り返ってほしいのです。なぜなら、ハー
ドウェアをコントロールすることはマシン語のほんの一■端であり、その前後の
プロセスにこそマシン語の真のテクニックがあるからです。
1990 年 9 月
マシン語プログラムを組む人の中には、プログラムの無駄やアルゴリズムな
ど、どうせアセンブルすれば隠れてしまうという人もいます。これは、マシン
語の基礎を省いてしまったことの弊害かもしれません。せっかく覚えたマシン
語ですから、面白くないこともそれなりに知っておくことが大切なのです。
とはいえ、基礎テクニックが基礎のままではャッハ。リ面白くありません。そ
こで、マンガを読むような気楽な気分で、つまらない基礎を知識の一部にして
しまいましょう。本書の基礎テクニックは、いわばプログラムの化粧品のよう
なもの。ちょっぴりプログラムにオシャレをするだけで、プログラムが見違え
るほど光り輝くかもしれません。
いかにも機械的な マシン 語です が、 アルゴリズムやテクニックというものに
は芸術に匹敵する‘美’が存在しています。それを追求するかしないか、そのこと
自体はプログラムを組む人の自由です。しかし、 マシン 語の技術 レベルの 差と
は、案外そんなところに潜んでいるのではないでしょうか。
徹学
高山
日主 ! IE
iv
目次
▲の章
二の章
秘伝の書を読むまえに-
—1
CZ
松り1印 合 oD
〇
問 1
セグメントの概念
芭蕪夫 •輪 田智(スイス)
6
問 2
マイナスの数値
初心者マー君(埼玉)
9
問 3
慣用句的論理演算
少年アセンブラ(岐阜)
11
問4
レジスタの 0 チェック
W 大商学部の星(ブライトン)
13
問 5
「 LEA 」 の効用
LEA 不信の JR マニア(神奈川)
15
問 6
RAM の特徴を活かす
どすこいドカ弁(香川)
17
問 7
FAR タイプのプロシージャ
メンチ(芸能界)
20
問 8
無駄命令とは
人間無駄蒸気(秋田)
22
問 9
ES レジスタの利用
ボケない老人(栃木)
25
問 10
「XCHG ES , DX 」 を実現
夜ふかしヒグマ(北海道)
27
問 11
セグメント*レジスタの初期化
魔法使い見習いジロー(魔法の国)
29
問 12
「 EXX 」 命令を実現
星降る乙女(与論島)
31
問 13
INC 命令とキャリーフラグ1
悩める美人の OL (福岡)
33
問 14
+/— を交互に
マシン西郷(鹿児島)
35
問 15
MOV 命令を減らす
浪花ぼてじゃこ物語(大阪)
38
問 16
ビット転送
Donald Tack (ロサンゼルス)
40
問 17
プロシージャへのジャンプ
ドラ Q (新潟)
42
問 18
命令の書き換え
ペンネーム猫目漱石(愛媛)
45
問 19
フラグで合図を送る
下宿先のドラ QII (山形)
48
問 20
範囲のある比較
ルートカ将軍(メソポチャ星)
51
問21
レジスタペアの値を 2 倍に
武蔵旅情(玄海灘)
53
問 22
マイナスの値を 1/2 にする
ツバメ小次郎(巌流島)
55
問23
かけ算を分解して高速化その 1
難破船長 パフ ニ (太平洋)
58
問 24
かけ算を分解して高速化その 2
ェスハ。一 魔 脳(宫崎)
60
問 25
CLD と STD
ニューハーフ占い師マーサ(東京)
63
問 26
CMP 命令でのジャンプ
ホワイトエンジェル(佐賀)
66
問 27
テーブルを利用したジャンプ
クラブ小話(和歌山)
68
問 28
一度の CMP 命令で5つの条件判断
サンタ日本代理人•黒須三太(富士山)
70
V
問 29
共通項のあるジャンプ
中年べビー(兵庫)
問 30
スタックを利用したジャンプ
半魚人(沖の鳥島)
問 31
ビット別のジャンプ
喫茶 シヱ ルブール ( 長崎)
問32
フラグ以外の条件ジャンプ
岩内保羅夫(マ界党)
問33
LOOP 命令の特徴
パチンコ老人(愛知)
問34
INC 命令とキャリーフラグ2
現地名•早ロトム(ニューヨーク)
問35
基礎的な疑似乱数
ペンギン野郎(南極)
問36
相加法による乱数
宝塚九二男(兵庫)
問37
乱数利用の基礎
男一匹長州軍団(山口)
問38
乱数の応用
旅先にて……風船のトラ(福井)
問39
乱数に変化をつける
中3あきな(石川)
問40
BP レジスタとは
悩める牧師(ニューギニア)
問41
パラメータ渡しプログラム • コード編
天オバーボン(酒乱界)
問42
ブロック充塡
名物•金脈おじさん(佐渡島)
問43
データ転送
根津見狐造(住所不定)
問44
データ高速転送
怪盗ルビィの指輪ちゃん(広島)
問45
3バイトの加減算
青い珊瑚礁(沖縄)
問46
ストリング命令のセグメント • オーノ くーライド
卑弥呼の部屋(奈良)
問47
十六進数を十進数に
番長ポロ屋敷(宮城)
問48
BCD 数値の加減算
カリブの海賊(ネズミーランド)
問49
データの左右反転
投稿マニア(徳島)
問50
実用できる左右反転プログラム
ピータン国王(岩手)
問51
AF フラグとは
間魔大王クッパ(地獄一丁目)
問52
「CMP DS,ES」 を実現
明治キメラ(長野)
問53
「CMP DX:AX,* * *」を実現
ニセ舞妓(京都)
問54
レジスタペアの NEG 命令
ヒッチくん(エ ジン バラ)
問55
ジャンプ代わりにリターン
白夜の棋士(静岡)
問56
ビット情報の縦方向コピー
眠りプログラマー(福島)
問57
ブロック比較について
ゲゲゲの Q 太郎(正マ界)
問58
SCASB 命令の効果的用法
ドブねずみ男(邪マ界)
問59
SCASB 命令とテーブル
目ン玉おやじ(本マ界)
問60
ベスト5のチェック
村長連合(大分)
問61
1バイト数値ソート
徳ノ川秀麿(島根)
問62
2 バイト数値ソート
田舎教師(茨城)
問63
プロック単位の文字列サーチ
貧乏神(貧民峡谷)
問64
連続データからの文字列サーチ
ましむご大僧正(魔心寺)
73
75
77
79
81
84
86
89
91
94
97
100
104
106
109
111
114
116
118
120
123
125
127
129
131
133
135
137
139
142
145
148
150
152
154
156
Vi
問 65 ブロック単位の文字列ソート
問 66 シフト JIS コードから JIS コードへ
問 67 アスキーコードのかけ算(筆算夕心〇
問 68 4 バイトのかけ算(筆算タイプ)
トマス.ェジ さん(富山)
ピーコー物 語(熊 本)
マシン 語歌人•俵まり(岡山)
ばぐちゃん(メモリの森)
問 69
問 70
問 71
問 72
問 73
問 74
問 75
問 76
AX+CX = BX (小数第一位七捨八入)
アスキーコードの割り算(小数第一位七捨八入)
BX+CX = BX.AL (小数第三位七捨八入)
BX . ALXBP=AX (小数第一位七捨八入)
アスキーコードから BX レジスタへ変換 アストロ
旅情の人(ベネチア)
影丸(三重)
サスケ(溢賀)
総領の甚六(高知)
•ベイダー ( TWS 星)
アスキーコー ドから BCD の数値へ変換
BCD の数値を アスキーコー ドへ変換
BCD をシフトする
技術部長ノホホン ( TRS 星)
銀河のシヱリフ(地球出身)
ドコデモガイジン(干葉)
問 77 BCD 数値の四捨五入
問 78 BCD 数値 XAL
問 79 BCD どうしのかけ算(筆算タイプ)
問 80 BX レジスタの値を BCD に変換
問 81 マシン語コード分割
問 82 BCD どうしの割り算(割る数の桁数固定)
問 83 内部割り込みと外部割り込み
問 84 MAKE の利用
スライムちゃん(テレビ界)
セブンっ子(鳥取)
ワシは父ちゃん(群馬)
デタラム.ぺテム(エジプト)
西洋の魔女(ノートルダム)
敷島博士(山梨)
天馬天之助(天国)
マシン語迷人(人間界)
問 85 BCD に関するミニ•テクニック 夢見る夢(夢脳)
問 86 テーブル処理で複雑な計算を さすらい人(礼文島)
三の章正しいマシン語のために
8086 ニモニック表
アスキーコードー覧表
159
161
163
167
169
171
173
176
178
181
184
186
189
191
193
198
202
204
208
210
213
216
221
vii
本書は、世界各地から……いや存在さえ定かでない謎の世界からも寄せられ
た多くの質問の中から、8086の秘伝として後世に残すべき基礎テクニックばか
りを集め、それに応える形で本にまとめ上げたマシン語の極意書であります。
その昔、日本には忍者という超能力にも似た秘術を使いこなす人間がいまし
た。もちろん、忍者は一朝一夕になれるようなものではありません。常に死と
背中合わせの厳しい修行を重ね、その中から自分の天分に見合った忍法を体得
した者だけが、忍者として一流の称号を得ることができたのです。いくら厳し
い修行に耐えようとも、オリジナルの忍法を開発できなかった者は、結局は三
流の雑魚忍群として虫けらのような一生を送るしかなかったのです。
しかし、一流の忍者にも老化という力の衰える時期が必ずやってきます。そ
の時、彼らは自分の秘術を残すために、その極意を巻物に記したといいます。
こうして、秘術は巻物とともに後継者に受け継がれていくのです。もちろん後
継者になれるのは、弟子の中から選ばれた、たった一人の超一流の忍者です。
. やがて、彼もその巻物に秘術を記す時が訪れます。こういった小さな歴
史が代々繰り返されることにより、巻物はその流派の『秘伝忍法帖』、あるいは
『秘伝の書』として無上の存在価値を持つようになるのです。つまり、「その巻
物さえ手に入れれば、無条件で超一流の忍者になれる」という神話が出来上が
るわけです。
こうなると、忍者であればその巻物が欲しくなって当然です。巻物を求めて、
密告、裏切りが横行し、ついには疑心暗鬼から内ゲバへと発展、修行を忘れた
凄惨な争いが起こるようになるのです。その結果、多くの忍者の里が闇から闇
へと自滅して いったの です。たった ひとつの 巻物のために . 。
それほどまでに人の心を狂わす『秘伝の書』……。その内容は、実は秘術を
記したものではなかったのです。そこには、精神的な極意、つまり平常心を養
うことの大切さや秘訣が抽象的に記されていただけでした。
忍の道を極めた者にとって、それこそがあらゆる忍法の極意であり、そこか
2
ら完成された秘術など一代限りのどうでもいい枝葉末節のことだったのです。
厳しい修行はそれを悟るための手段であり、秘伝とはそういった悟りの境地を
伝えることなのです。
すなわち、『秘伝の書』の価値はそれに見合う修行を積んだ者にのみ理解され、
修行中の者には文面通りの内容しか伝わらないのです。例えば、部屋にある敷
居の上は誰でも歩くことができますが、千尋の谷の上に架けられた同じ幅の木
の上を平然と歩〈ことができるでしょうか。誰にでもできる簡単なことを、環
境を選ばず冷静に実行できるようになるには、たゆまぬ基礎訓練が必要なので
す。その中から自分の才能に適した新しいものを発見した時、オリジナルの秘
術が生まれるのです。そして、その精神を平易に教えてくれるのが『秘伝の書』
というわけです。
マシン語でプログラムを組めるようになると、どうしてもアッと驚く秘術ば
かりを開発したくなります。しかし、秘術の陰には基礎テクニックがあるので
す。あくまでも、秘術はその延長線上にあることを忘れないでください。
本書にある基礎テクニックは、まさにマシン語のための『秘伝の書』となる
べき空気のような存在です。あるいは、「なんだ、こんなもの!!」と思うかもし
れません。基礎とはそんなものです。しかし、つまらないことを当り前に使え
るか使えないかで、プログラムは大きく変わってくるのです。本書の内容がつ
まらなく思えなくなった時、オリジナルの秘術的マシン語プログラムが完成す
る時といえるでしよう……。
なお、本書は8086系(8086,80286,80386 •••) を CPU とするコンピュータ用の
マシン語プログラムを、 MS - DOS の MASM 上で開発することを前提に書かれ
ています。したがって、プログラムやテクニックを実用化するためには 、 MASM
を使用するための基本知識が必要です。
ニモニックやアセンブラの 必要性がわから ない 場合は、まず マシン 語の基礎
を教えてくれるような本を読んでください。本書では、 マシン 語を覚えるため
の 基礎は 学ぶ ことができません。あくまでも、 「マシン 語 テクニックの 基礎を マ
シン 語を使って学ぶ」どいうことが目的です。
また、お手持ちのアセンブラによっては、二進数が使用できないとか色々な
3
制限があることがあります。そういった入門用のアセンブラをお使いの方は、
できるだけ早いうちに新しいものを手に入れることを考えたほうがいいでしょ
う。少なくとも、本書のプログラム程度は問題なくアセンブルできるようなも
のでないと、マシン語で秘術を凝らすには荷が重いかもしれません。まずは、
アセンブラを空気のような存在にすること、それがマシン語の最初の基礎テク
ニックです。
では、ごゆっくりと秘伝の世界を楽しんでください……。
4
■■■ セグメント痛念
、ブバブー。パブちゃんは3歳ですゥ。でも、もう英語と日本語とフランス語とドイツ語
がペラペラですゥ……パブ。ここまでくると、どんな国の言葉でもすぐ覚えられるよう
になるのですゥヨ。生まれた時から、そういう環境に住んでいたから、言葉に対する違和感な
んてないんですゥ……パブ。
もう人間の言葉は飽きたから、次にマシン語を覚えたんですゥ……パブ。それは、8ビットの
代表格 Z 80ですゥ。でも、あれは思ったより簡単だったから今度は16ビットの代表格8086に
挑戦しようとしているのですゥ……パブ。パブちゃんの覚える方法は、わからないことがあっ
たらすぐ聞いて覚えてしまうことですゥ。こういう時は、小ちゃいほうが得ですねェ……パ
ブゥ。
質問というのは、セグメントという実体がよくわかんないんですゥ。バンク切り換えでもなさ
そうだし、いったいこれはどういったものなんですゥ……パブ? バブちゃんにもわかるよ
うに、やさしく教えてちようだいです ゥ。 では、パブパブ ゥ。
芭蕪夫•輪田智(スイス)
■答- .
スイスという国は、北海道の半分ほどの狭い国土の中にドイツ語、フランス
語、イタリア語、ロマンシュ語が公用語として存在しており、しかもほとんど
の人が英語を話せるというから驚いてしまいます。
パブちゃんの才能は、きっとそんな環境の中で生まれ育ったのでしょう。そ
れにしても驚きですゥ パブ。
実は 、 Z 80などの8ビット CPU から8086系の16ビット CPU に移った場合、
このセグメントの概念がひとつの壁になっているケースは少なくありません。
ベルリンの壁も崩壊したことですし、ぜひセグメントの壁も取り崩してしまい
ましょう。まず、8086系 CPU の大きな特徴を改めて確認してください。
① レジスタは16ビットで構成される
② メモリのアクセス範囲は 1 M バイトである
これら2つの特徴から、必然的にセグメントの概念が生じてきたのです。16
ビットで数えられる範囲は、ご存じのように〇〜64 K バイトです。ところが、メ
モリのアクセス範囲は 1 M (64 KX 16=1024 K ) バイトですから、16ビットで
は全メモリ空間を示すことができません。そこで、特別な工夫をすることにし
たのです。
この特別な工夫(セグメントの概念)とは、簡単に言うと次の問に対する答
のようなものです。
10本の指で100まで数えてください
これに対する代表的な答は、左手の指に10の重みを持たせ、右手の指で10数
える毎に左手の指を1本づつ折っていくという方法でしょう。セグメントの概
念は、まさにこのことなのです。2つの16ビットの数値の一方の刻みに、16の
重みを持たせることにより 1 M バイトを表現するのです。
この16の重みを持たせた数値のほうをセグメントアドレスと呼びます。1つ
の刻みが16の重みを持っていますから、セグメントアドレスが1増えることは
メモリ上で16バイト増えることを意味しています。そして、もう一方の16ビッ
卜の SH 直は、オフセットアドレスといい、このセグメントアドレスにオフセッ
トアドレスを与えることによりメモリ位置を決定するのです。すなわち、実行
アドレスの計算は、セグメントアドレスを16倍した直にオフセットアドレス
を足すことによって求められます。また、オフセットアドレスで数える〇〜64
K の範囲を1つのセグメントといい、セグメントアドレスがこの1つのセグメ
ントの開始アドレスを決定しているのです。
8086は4つのセグメント用レジスタによって、全メモリ空間を管理していま
す。
CS •••コードセグメント.レジスタ
DS •••データセグメント•レジスタ
ES •••エタストラセグメント•レジスタ
SS •••スタックセグメント•レジスタ
これらのレジスタのうち、プログラムで直接操作するのは DS と ES です。特
7
に、 DS に対しては暗黙に指定されている命令が豊富にありますから、頻繁にア
クセスするデータはデータセグメントに設定するようにします。一方、 ES レジ
スタに対する命令は、わずかにストリング命令があるだけで、あとはセグメン
卜 • オーバーライド•プリフィックス命令を使うことになりますから、同時に
複数のセグメントをアクセスする場合に用いることが多いようです。
セグメントに慣れないうちは、プログラムの先頭で DS 二 ES = CS とし、プロ
グラムで BP レジスタによるメモリ參照を行わなければ、1つのセグメント内だ
けでプログラム作りができます。こうすれば、セグメントをまったく意識せず
に済みますから、初心者でもプログラミングそのものに集中できるようになり
ます。
いずれにしても、いつかはセグメントを理解した上でプロダラミングしなけ
ればなりません。バブちゃんも、すぐにそういう日が来ることでしょう。セダ
メントでも何でも、すべては慣れなのですゥ……パブ。
マィナスの数値
(土じめまして。ポクはこれまで ゲーム ばかりやっていたので、学校では「動くパソコンソ
^フト」と言われています。でも、実は秘かに ゲームから 脱皮しようと思い、 マシン 語を
勉強し始めています。 マシン 語といっても、やっと ニモニックの 意味と アセンブラの 必要性が
わかりかけてきた程度です。
ところで ポクの 読んだ本によると、一般にアセンブラの ソースリスト 上では十進数表記も可
能と書いてあります。といっても、ニモニックで用意された命令で扱える数値は1バイ ト
(0 〜 FF h ) か2バイト (0 〜 FFFFh ) ですから、十進数でいえば〇〜255まで (1 バイ トの 場合)
か、〇〜65535まで (2 バイトの場合)となるはずです。でも、でもでも、ですよ。ある時、雑
誌に……
XPOS DB -10
となっているソースリストがあったのです。ハツキリ言って、これがどういう数値を表すのか
意味がわかりません。もちろん、十進数ならわかります。いったい、十六進数でマイナス(一)
とはいくつのことですか。ちなみに、ポクはまだ本物のアセンブラは持っていません。早くア
センブラがほしい……。
初心者マー君(埼玉)
■答 -《
初心者からの質問というのは未知数の魅力にあふれていて、内容にかかわら
ずとても新鮮に感じます。ついつい自分の過去を思いだしたりします。
マシン語が上達するひとつのカギは、自分の持っているアセンブラの能力を
どこまで発揮できるかにあります。とはいえ、最初から高級なアセンブラを持
てばいいというものでもありません。あまりアセンブラが高級だと、 マシン 語
を覚える前にアセンブラのマニュアルに圧倒されてしまうからです。だから、
最初は操作が簡単で安価な入門用アセンブラを手に入れ、自分の技術レベルに
合わせてグレードアップするほうがいいでしょう。
ということで、初心者マー君の疑問に一気に答えてしまいましょう。な一に、
答は簡単です。マシン語で扱う数値は、使う人の気分次第でプラスにでもマイ
ナスにでもなるのですから。つまり、ループ ( FF H の次は 0) している数値を前
向き(プラス方向)に数えるか、後ろ向き(マイナス方向)に数えるかの違い
があるだけなのです。
だから 、一 10は十六進数でいえば
F 6 H というわけです。もし、ここでの命
令が 「 DB 」 でなく 「 DW 」 であれば、一
10は FFF 6 H となります。でも、でもで
も、ですよ。これで若葉マークが取れ
たなんて思ってはいけません。なぜな
ら、演算の結果、サインフラグを見て
条件分岐をさせる場合は、コンピュー
夕はデータの最上位ビットを見
て +/— を 判定す るからで す。 つまり、
数値としてはすべてをプラスと考えよ
うがマイナスと考えようが自由ですが、コンピュータにその判断をさせる場合
は、次のようにキチンと区別をしなければならないということです。
1 バイトの場合: 00 H 〜 7 F h
FF h 〜 80 h
2バイトの場合: 000 0 H 〜 7 FFF h
FFFFh 〜800 0 H
= 0-127 (プラスの数値)
=— 1 〜 一 128 (マイナスの数値)
= 〇〜32767 (プラスの数値)
=—1〜一32768 (マイナスの数値:)
マイナスという感覚で数値を扱う時は、ここまで理解した上で使用しないと
思わぬバグに陥ることがあります。そして、こういう一見つまらなさそうな理
由によるバグが、実は最も恐ろしい落し穴なのです。しかし、マイナスが自由
に使えるようになると、プログラムが急に進歩するのも事実です。初心者マー
君がプロダラ•マー君になる日も近いことでしょう。
なお、雑誌などに発表される簡易的なアセンブラでは、マイナスが使用でき
ない ものもあります。プログラム技術の向上のためには、そのようなアセンブ
ラからはできるだけ早く卒業し、互換性の高い MS-DOS 上の MASM を準備し
たいところです。
10
1 翩句的論理演算
jp ' クはマシン語を覚え始めたばかりの小6です。まだ本当に短い プログラムしか 組めま
せん。ポクのマシン語の先生は中2の兄ですが、その兄も RPG でいうならレベル5 くら
いみたいです。ポクはレベル2 くらいでしょう。
でも、兄は論理演算について一応知っています。ボクも兄に教わった ので、 論理演算をすると
ヒツトがセツトされたり、リセツトされたりするということはわかるようになりました。 た
だ、まだそれがどんな時に必要になるのかはわかりませんけど。
ポクは、いま昔の簡単なゲームを見つけて、それを逆アセンブルしてプログラムの仕組みを覚
又よつとしています。昔のゲームっていうのは、これが本当に商品だったのかと思うほどレべ
ルが低かったのですね。プロテクトなんて、もちろんナシです。でも、結構論理演算なんかも
使っているみたいです。
ところが、よく出てくる論理演算に 「XOR AX , AX 」 と 「OR AX , AX 」 というのがあります。
紙に書いて結果を確認すれば、 AX レジスタの値がいくつになる かは わかります。でも、 なん
のためにやっているのか、その目的がさっぱりわかりません。昔の ゲームといっても 結構む
ずかしいんですね。どうかよろしくお願いします。
少年アセンブラ(岐阜)
| 答 ---<
こり ゃ マイツタ!?
小学6年生でマシン語を始めてる……だって!?それも、論理演算にまでコ
マを進めてる . だって!?オドロキ桃の木サンショの木 . です!!
しかも、マシン語の勉強法に昔のゲームソフトを解析するなんていうのは、
将棋でいうなら最初から最善手を指しているよう なべ ストウェイです。 なにし
ろ、昔のゲームというのはプログラムの内容がほとんど画面に反映されるよう
になっていますから、解析してプログラム手順を覚えるには最高の教科書なの
です。もしかすると、アツという間に先生であるお兄さんの レベルを 越えてし
まうかもしれません。
……が、そうなるためには今回の質問のようにプログラムの目的をしっかり
と理解することが大切です。だから、この本が手元にあるって ことは、 もはや
虎の巻を手に入れたようなものです。
さて、まず論理演算による各ビットの変化についてですが、これはマシン語
の 入門書であればどんな本にでも載っていることなので、ここでは省きます。
問題は、いかにして論理演算の用途を把握するかということです。
その理由は、論理演算については純粋にビット操作が目的の場合と、フラグ
を変化させるのが目的の場合があるからです。ビット操作が目的の場合は、そ
のビットの役割を調べればわかりますが、フラグを変化させることが目的の場
合はいくらビットの内容を調べても結論は出てきません。
では、どうすればいいかというと、単純に暗記すればいいのです。おもに使
用される慣用句的論理演算は次の3種類ですから、暗記というほ ど大裝裟なこ
とでもありません。とはいえ、使用頻度はビット操作が目的の論理演算より多
いくらいですから、とりあえずは深く考えずに覚えてしまいましょう。
XOR reg.reg
演算の結果が常にゼロになりますから、 「MOV reg,0」 の代わりによく用い
られます。
ただし、演算によるフラグ変化がありますから、そのことを考慮した上で使
い分けなければなりません。
OR reg’reg
論理演算によるフラグ変化を利用し、 「CMP reg,0」 の代用として、あるい
はキャリーフラグのリセット用としても使われます。
AND reg.reg
rOR reg,reg」 とまったく同様の目的で使用されます。
(注)第1オペランド (reg) と第2オペランド (reg) は同じレジスタ。
これらは単なる慣用句ですから、論理演算の機能を本当に利用したとはいえ
ないのですが、プログラムがちょっぴりオシャレしたような気分になれるで
しょう。しかし、本当にカッコイイのは論理演算を2つ以上組み合わせて目的
の データを 作り出す、というような使い方をしたプログラムなのです(例えば、
XOR をとってから AND をとる . 等)。
その時には、 マシン 語の レベル も10を超えているでしょう。でも、小6 で そ
こまでカッコイイと、ハッキリいって大人はつらい . 〇
12
J/ は現在イギリスはブライトンに住んでいます。本当の目的は一人旅ですが、最初の8週
間は英会話のスクールに通い、まずは外国生活に慣れるつもりです。いま、ちょうど半
分が過ぎたところですが、夏なのにカラッとした気候のブライトンにいると、このまま住み着
きたくなるほどです。
でも、日本では大学5年生に籍を置いたままですから、スクールの後は予定通り旅をして日本
へ帰ります。帰国予定は12月です。卒業のほうは、具体的には秘密ですがちゃんと手を打っ
てありますから大丈夫でしょう。
ところで、どこにいても気になるのは覚えかけたマシン語のことです。だから、英語の辞書と
マシン語の本はいつもカバンに入っています。その本には……、
「レジスタがゼロかどうかを判定するには、 「CMP AX,0」 より 「OR AX,AX」 がいい』
と、書いてあります。理由はプログラムに要するメモリが少なくて済むからだそうですが、他
にもレジスタのゼロチェックの方法があると聞いたことがあるのですが、何かうまい方法が
あったら教えてください。
W 大商学部の星(ブライトン)
■答-«
ム、 この男性はどこかで見かけたことがある……。それも、つい最近などと
いうものではなく、なぜか生まれた時から現在まで、そのすべてを知っている
ような気がしてならないのだが……それが誰なのかはわからない……ウ 〜ム。
マシン語を始めたばかりは、 プログラムの 長さとか速度などまるで気になら
ないものですが、やがてそれに目覚める時がくるのです。その時こそ、マシン
語が新たなる パズルゲームに 発展する日なのです。あなたに も、ついにその 日
がやって来ましたか。
質問の回答をする前に、なぜ 「CMP AX ,0」 より 「OR AX , AX 」 がいい
のか考えてみましょう。答は簡単です 。 「CMP AX ,0」 では、命令にメモリを
3バイト使用し、実行に要する時間は4クロックかかりますが 、 「OR AX ,
AX 」 ならばメモリは2バイト、実行時間は3クロックで済むからです。もちろ
13
ん、これらの命令は AX レジスタに限らず使うことができます。ただし、すべて
のフラグが同じ変化をするわけではありませんから、ソックリ同じとはいえま
せんが……。そのことを知った上でなら、実用上は同じと見なしても差し支え
ないでしょう。
早い=タイムクロック数が少ない
安い=使用メモリ数が少ない
これが、うまいブログラムというわけです。では、質問への回答です。結論
からいうと、演算の結果に従ってゼロ.フラグは変化するが、レジスタの値は
変化しないという条件を満たせばよいことがわかります。しかも、 「 CMPreg ,
0」より、使用メモリまたはクロック数で有利でなければなりません。そこで、
こういう場合には次のようにします。
DEC
regl 6
INC
regl 6
INC
regl 6
または
DEC
regl 6
どちらも命令に要するバイト数、実行クロック数は同じです。足して引いて
も、引いて足しても、変化するのはフラグだけですから、レジスタの内容は壊
れな いわけです。 まさに、 ハ。ズルではないです か . 。
ここでレジスタを16ビットに限定していることに注意してください。もし、
使用レジスタが半分の8ビットレジスタの場合には、逆に 「 CMP 」 命令を素直
に使ったほうが有利になります。なお、1つの命令に対するバイト数と、クロッ
ク数は三の章の8086ニモニック表を見ればわかります。クロックというのは、
その 命令に必要な時間の単位ですが、実際の時間は そのマシンの 基本周波数 (8
MHz とか10 MHz ) によって変わります。
J / は鉄道マニアです。 JR の全路線を踏破するのが目標ですが、お金と時間のかかることな
似 のでいつ達成できるか、自分にもさっぱりわかりません。
そこで、パソコンを使ってひと足お先に画面上で全国踏破しようと思うのですが、今度はプロ
グラムで頭を使いデータ入力で時間を使い、やっぱりいつ達成できるのかわかりません。それ
でも、こちらのほうはお金がかからないだけ助かってはいますけど……。
実は、最初はプログラムを BASIC で組んでいたのですが、あまりに遅いためマシン語でやろ
うと決心したのです。ただ、マシン語でまともなプログラムを組むのはこれが初めてなので、
マシン語といっても幼稚なものです。そこで、恥ずかしいのですが未熟者からの質問と思って
教えてください。よく雑誌などで……
[LEA ****] 命令よりも [MOV OFFSET 木***]命令のほうが 実行 スピードが早いの
で、 LEA の代わりに MOV 命令を使用しています。
……と、書いてある投稿記事があります。確かにニモニック表では LEA 命令は 2 + EA クロック
で、 MOV 命令は 4 クロックです。これでは LEA の存在する意味はナイも同然です。これは一体
どういうことでしよう。
LEA という命令が存在している以上、なんらかの意味があると思うのですが、ちなみに、現在
のプログラムは乗車ルートを決めるという段階で、一応思考ルーチンとなっています。本当に
意味がないのであれば、思考時間の短縮のために LEA を MOV 命令に代えるべきでしょうか?
LEA 不信の JR マニア(神奈川)
■答 -《
この答は簡単ですね。 LEA 命令だって人の子、いやマシンの子です。存在す
るからにはそれなりの意味があるのです。まずは質問にあるような単純な場合
を考えてみましょう。
MOV SI'OFFSET DATA 1 LEA SI,DATA 1
4 クロック 8 ク□ック
^5
このように、ダイレクトメモリアクセスの場合には、 LEA 命令は 2 +EA
(EA 二 6) でトータル8クロックとなり、 MOV 命令の倍の時間がかかることに
なります。
そこで、まずはこのクロックというのは具体的にどの程度の時間をいうのか
計算してみましょう。ただし、割り込みや DMA などによるウェイトは考慮に入
れません。また、基本周波数は10 MHz としています。
1クロック=1 + 10+1000 + 1000秒
= 0.0000001 秒
これが1クロックの実際の長さです。つまり、 LEA 命令を MOV 命令に置き換
えると、それだけで0.0000004秒高速になるというわけです。
しかし、だからといって、 LEA 命令が不要だというわけではありません。 LEA
命令は、インデックスレジスタ等によるメモリ参照に対するオフセットアドレ
スを得たい時にも活用できるのです。例えば次のような場合です。
LEA SI,[BX + DI + DISP1]
これで、 SI レジスタへオフセットアドレスが格納されます。もちろん、この
SI に求めたオフセットアドレスを単純に使う場合であれば、なにも SI へオフ
セットアドレスを求めるまでもなく、このアドレッシングをそのまま使えばす
むことですが。求めたオフセットアドレスをさらに加工したり、データエリア
のアクセス範囲をチェックしたり、それなりに価値がある命令なのです。決し
て存在価値がナイだなんて思わないでください。
なかには 、 「MOV reg , OFFSET * * * *」よりも意味がハッキリとすると
いう観点から、積極的に使っている LEA 信者もいるくらいです。こうなると、
どちらを使うほうがよいかは、趣味の問題となってしまいます。まあ、質問者
の例では、プログラムの高速性から MOV 命令を使っても問題はないでしよう。
i6
_
K スコ〜ィ!!
朝もハヨからドスコ〜イ。ワシは大横綱千代の富士。
……を目指して、新弟子検査を受けようとしている自称超横綱万代の富士(まよのふじ)っす。
身長183センチを目標に、168センチの身体にムチ打って連日ドカ弁を食べているっす。おか
げで体重だけは115 kg もあるっす。ア、いま中3っす。
寝てもさめても相撲だったのに、なんの間違いか誕生祝いにパソコンがほしいと言ってし
まったっす。もちろん冗談100パーセントのつもりだったす。これまでほしいものを一回で
買ってもろたことなんてなかったすから。ところがなんと、誕生日の日学校から帰ると、机の
上には本物のパソコンが……。
てなわけで、最近では BASIC を通り越してマシン語に夢中っす。ところで、メモリには ROM と
RAM があるっすが、 ROM だけじゃプログラムは無理ってことは理解してまっす。ワークエリ
アがなけりゃプログラムは組めないっすもんね。
でも、この前 『 RAM の特徴を利用したプログラム』があるってことをどこかで耳にしましたっ
す。これはいったい、なんのこっすか?
どすこいドカ弁(香川)
■答-- •
いよいよ マシン 語も体力勝負の時代に突入したようですね。ドスコ〜イのか
け声と共に マシン 語が土俵の外へ突き飛ばされそうです。
さて、プログラムであれば BASIC であれ マシン 語であれ RAM は絶対に必要
ですが、これは基本的には変数保持のためにワークエリアが必要だからです。
例えば、 カーソル やキャラクタの表示位置を示すワークエリアとして、よく
rxposj 「YPOS」 というラベル名を使用しますが、この中身をプログラム中
に BX レジスタにロード ( BL レジスタに X 座標、 BH レジスタに Y 座標)すると
仮定してみましょう。
これを通常のプログラムー①と RAM を利用したプログラムー②とに分けて
組んでみたのが次の2つです。どこがどう違うか、それぞれの特徴を見極める
つもりでプログラムを見てください。なお、プログラムの右側にある数字は、
その命令に必要なバイト数を表しています。
n
M 0 V_BX EQU
OBBH
WPOS PR 0 C
DB
M 0 V _ BX ; ^
XPOS DB
〇 ;
MOV BX ,0
YPOS DB
0 ;」
WP 08 ENDP
XPOS
DB
0
YPOS
DB
0
WPOS
PROC
MOV
BX , W 0 RD PTR CS : XPOS
WPOS
ENDP
!
ここで②の先頭データ OBB H が 「 MOVBX ,...」 のオペレーション•コード
であることに注意してください。また②は、見かけ上データの集まりのように
も見えますが、逆アセンブルしてみると 「 MOVBX ,0」 をハンド•アセンブル
したものとなっていることがわかります。
どちらのプログラムも、これ以外の場所で 「 XPOS 」「 YPOS 」 の中身を操作
する命令に関してはまったく同じ条件です。ということは、 RAM を利用したブ
ログラムー②では、通常のプログラムー①より命令に要するメモリ数が4バイ
卜少なくて済むということがわかります。
さらに、 BX レジスタにデータをロードする命令も、① (16 クロック)に対し
②は4クロックと1/4になっています。したがって、この3行分だけに関して
いえば、メモリ数もタイムクロック数も②は①をかなり節約した形になってい
るわけです。こうなると、どちらが得かはもう明白です。いかにも、①のプロ
グラムは素人っぽく見えてきますね。
とはいえ、これはテクニックとしてはかなり特殊な部類に属し、かつ思わぬ
バグに陥る危険性も秘めているのです。不用意に利用するのではなく、メモリ
の節約と速度の追求がどうしても必要な時だけに限定しなければなりません。
というのは、8086には実行速度の高速化を図るため、6バイト先読みの命令
キュー (Instruction queue ) があるからです。この特徴を十分に考慮しないと、
迷宮入りのバグに泣かされるかもしれません。簡単な例として、次のようなプ
ログラムを考えてみましょう。
18
MOV—BX
EQU
OBBH
MOV
ALJ2 H
TST 1:
MOV
CS : XPOS,AL
DB
MOV BX ; コ
XPOS
DB
0 ;
MOV BX,0
YPOS
DB
0 ;-
この例では、 TST 1 というラベルの命令が実行される時、すでに 「 MOVBX ,
0」も CPU の命令キューに格納されています。したがって、ブログラム実行後の
BX レジスタ の値は依然0のままです。もちろん、 XPOS のメモリの値を確認し
てみると 12 H となっていますから、この先読みに気が付かないと永遠に悩むこ
とになってしまうのです。
また、このようなプログラムが通用するのはプログラム自体が RAM に置か
れるということが絶対条件ですから、将来 ROM 化するような場合はキチンと
ワークエリアを分離した①の書式にしなければなりません。あくまでも 「RAM
の特徴を利用した」ということを忘れてはならないのです。さらに、他の言語
系へ移植をする可能性がある場合や、多人数でブログラム開発をするような場
合には、十分検討してからにしてください。
しかし、本書のプログラムにおいては、原則的に ROM 化することまでは考え
ていませんから、この先さらに RAM の特徴を利用したプログラムが現れてき
ます。その際、特に RAM 専用という断りを入れませんので、もし ROM 化予定
のプログラムに本書のテクニックを応用したい場合は、それなりに RAM エリ
アを活用するよう、各自で考慮してください。
そもそも、タダで便利なものにはどこかに条件があるというのは世の常なの
です。香川のどすこいドカ弁君にハ。ソコンがプレゼントされたのも、きっとそ
の裏には別の願いがあったんではないっすか。身長/体重のバランスからして
19
n_
タイブのプロシ-ジャ
_の顔、どう歌手の森田進一に似ているでしよ。次は岩崎ひとみ、その次は三木ひろしと
一村田春夫の合成顔……。
おっと、手紙では自慢の百面相がお見せできなくて残念無念。私は、芸能界一のモノマネ男と
言われているメンチで〜す。気楽な商売に見えるでしようけど、これでも結構大変なんですヨ
〜ッ。常に新ネタを考えないと忘れられてしまいますからネ。
そこで、芸能人の顔の特徴と自分でできる顔の特徴をコンピュータに登録し、ネタに困ったら
「次は野口四郎のマネが可能です」というような回答が出るように、秘かにマシン語でプログ
ラムを組もうと思っているのです。
一応、セグメントについては勉強して理解していますが、どうも異なったセグメント間でのサ
ブルーチンの定義や コールの 方法がわかりません。なにしろ、プログラミングはモノマネ芸と
違って素人ですから……。
どうか、みんなに内緒でソッと解説してください。これも新ネタと同じで、いわゆる企業秘密
としたいので〜 ス。
メンチ(芸能界)
■答- •
テレビで華々しく活躍中のメンチさんも、やはり陰では人知れず苦労をして
いたのですね ェ。 しかも、モノマネ同様、イヤそれ以上にプログラムに対する
テーマが素晴らしいではないですか。プログラムの勉強をしても、いざプログ
ラミングとなると「何をプログラムしていいかわからない」という人が多いの
ですが、このあたりはさすがプロの芸人といえるセンスのよさで〜ス。
r . で〜ス」だけマネしてもモノマネになりそうもないので、素直に質問
に答えることにします。本書では、原則として MS - DOS 専用のアセンブラ
「 MASM 」 の使用を前提としていますが、 MASM では1つの独立した処理体系
をサブルーチンとはいわずにプロシージャと呼んでいます。
異なるセグメントにおけるプロシージャは、単にプロシージャのタイプを
FAR とするだけで、 FAR タイプのサブルーチン(プロシージャ)が定義されま
す。もちろん RET 命令も自動的に FAR タイプに変換されます。実際に、セグメ
20
ント CODE 0から CODE 1に定義した FAR タイプのプロシージャ TEST 1を
コールする例を次に示します。
FAR タイプのプロシージャの定義
なお、定義した FAR タイプのプロシージャに複数の RET 命令を使った場合で
も、それらはすべて FAR タイプに変換されます。しかし、プロシージャを定義
する場合は、プログラムの保守性やわかりやすさなどの点から、できるだけ入
口と出口は1つにするよう心がけるべきです。
また、割り込みプロシージャの場合には、割り込み専用の IRET 命令が使われ
ます。これは、割り込み処理へ制御が移動した場合、 CS、IP と共にフラグが
PUSH されるため、最後の IRET 命令ですべてを POP するためです。
今度は、こちらからお願いです。ぜひ、百面相モノマネの秘伝を公開してく
ださい。待っていま〜ス。
CODEO
SEGMENT
CALL FAR PTR TEST 1
CODEO
ENDS
C0DE1
SEGMENT
TEST 1
PROC FAR
RET
TEST1
ENDP
C0DE1
ENDS
_
■= l = r 春とは爆発だァ!!
冃オレは高3。あり余るエネルギーを、走ることで燃焼させている。別に陸上部に所属し
ているわけじゃないから、距離はたったの3 km さ。だけど、ほとんど毎日のように走ってい
る。正直いって走っている時はメチャ苦しい。顔は苦痛にゆがみ心臓はオーバーヒート寸前
……。ここで歩けばどんなに楽かと、いつもそれだけを考えて走っている。
でも、それを我慢して走り終わると、これがまた何とも言えない壮快感。誰もホメてくれなく
ても、オレはその瞬間が大好きなんだ。無駄なことをしている、なんて言うヤツもいるけどネ。
無駄なことができるってのは、ゆとりがある証拠さ……。
ところで、コンピュータにも無駄命令ってのがあるって話だけど、こればかりは自分のこと
じゃないからよくわからない。ニモニック表を見たら 「 NOPJ という命令があったけど、これ
が無駄命令のことなんだろうか。
まさか、パソコンにもエネルギーのあり余る時があるっていうんじゃないだろうな。よくわか
らないから、ひとっ走りしてこようっと!!
人間無駄蒸気(秋田)
■答- .
いいなァ、無駄なことができるなんて!!
……と 言いつつ、 私もま だ 現役で 走って います。でも、それはエネルギーが
余っているからではな〈健康のためです。もちろんエネルギーは消耗しますが、
これは回復力という別のエネルギーを呼び出してくれますからね。決してエネ
ルギーの無駄な消費ではないわけです。
つまり、一見して無駄に見えることが実は無駄なんかではなく、身体にとっ
て重要な役割を果しているということです。コンピュータにおける無駄命令も、
本当に無駄なら誰も使わないはずです。と考えると、無駄命令という言葉が存
在すること自体、そこには無駄ではない何かがあるはずです。
そこで、まずは質問にあった 「NOP」 という何の役にも立ちそうもない命令
を見てみましょう。確かに、この命令はフラグ変化も伴わないし、実行結果を
見ても何も残してくれません。でも、これは決して不要な命令なんかではない
22
のです。その証拠に、次のような役に立つことを実行してくれています。
(1) メモリを1バイト確保する
(2) 3クロックという時間を消費する
メモリを1バイト確保してくれるということは、必要に応じてそのメモリを
利用できるということです。例えば、衝突をチェックするサブルーチンがある
とすると、その先頭に 「RET (二 C 3 H )」 を入れれば、簡単に不死身モードがで
きてしまいます。
衝突のチェックあり 一> 衝突チェックスキップ(不死身モード)
CHECK : NOP
CHECK: RET
RET
RET
また、3クロックという時間の消費は、外部機器や特殊デバイスとのャリト
リをする場合に、タイミングを取るための最小ウェイトとして活用されます。
どうですか。これら2つの役割だけでも 「 NOP 」 が役に立つ命令であること
がわかりますね。
さて、無駄命令といわれているものには、このほかにもタイマーとしてのウェ
イトルーチンがあります。例えば、カーソルなどはウェイトを入れなければ早
すぎて思い通りに動かせませんし、ゲームでもスピードの調節が不可欠です。
このような場合、正確には割り込みによってキチンとしたウェイトを取らなけ
ればなりませんが、簡単なルーチンの場合は次のようにループによってウェイ
卜調整をすることもあります。
WAIT
PROC
MOV
CX,30
WAIT1 :
PUSH
AX
POP
AX
LOOP
RET
WAIT 1
WAIT
ENDP
— CX の値によって長さを調節する
23
このようなプログラムを一般に無駄命令と称しているわけですが、本当に無
駄なのはダラダラと不要に長い下手なプロダラムというべきです。必要がある
から使われているウェイトルーチンは、かわいそうにも俗称だけが無駄命令と
いうわけです。
もっとも、人間の反応がコンピュータ並みに早ければ、大半の俗称無駄命令
も省けることになりますが……。そうなると、コンピュータそのものが無駄な
存在になってしまいます。
24
^ _
J / は、定年退職してからパソコンを始めた者です。息子のパソコンをいじって いる うち
W に、ついマシン語なるものに興味をもちました。ところが、年のせいか、どうも融通が
ききません。いつも、レジスタが足りなくて 「 PUSH / POPJ ばかりを使ってしまいます。も
ちろんワークエリアの存在は知っています。しかし、これはワークエリアを使っても解決する
ような問題ではないと思うのです。
いま、 DS レジスタに 800 H を足したいのですが、あいにく ES レジスタしか空いていません。な
んとか、 「 PUSH / POPJ 地獄から抜けたいのですが……。
PUSH
AX
MOV
AX,DS
ADD
AX ,800 H
MOV
DS,AX
POP
AX
やっぱり、これしかナイものでしようか。私にはこれ以上の案はでませんが、老人でもプログ
ラムの格好は気になるものです。
ボケない老人(栃木)
■答 -ィ
パソコンに年齢なんか関係ありません、という見本のような例です。コン
ピュータといえば、ついこの間までは大型の電子計算機を意味していたのです
から、若い人も年とった人もスタートは一緒です。
そんなことより、新しいことにチャレンジできるなんて、まさに青春まっ盛
りではないですか。おまけに、 「 PUSH / POP 」 地獄から脱却したいとは、なん
て素晴らしいことなのでしょう。プログラムの格好を気にするなんていうのは、
プロのプログラマーで もなかなか言えない セリフ です。
ところで、このようなケースには実際によく出会います。特に、データの転送
などでは DS : SI/ES : DI レジスタでデータのアドレスを指定し、 CX レジスタを
カウンタに使うことが多いですから、途端にレジスタ不足になってしまいます。
25
「 PUSH / POP 」 命令は確かに便利ですが、 ES レジスタが空いているならば、
これを利用しないのは、やはり無駄といえるでしよう。もちろん、 ES レジスタ
には演算命令がありませんからワーク.レジスタとして活躍してもらうことに
なります。次の例を參照してください。
MOV
ES,AX
MOV
AX,DS
ADD
AX ,800 H
MOV
DS,AX
MOV
AX.ES
質問にあった 「 PUSH / POP 」 を使用した方法では、使用メモリ数=9バイト、
クロック数二26となります。一方、こちらの方法では、使用メモリ数=11バイ
卜、クロック数=12です。たったこれだけでも、14クロックも節約したことに
なります。もし、ループ内処理であれば、14 XN (ループ数)クロックの節約で
すからかなりのものです。セグメント.レジスタといえども遊ばせておくこと
はないのです。
では、栃木のおじいちゃん、格好のいいマシン語プログラムを目指して、ま
すます頑張ってください。
26
^■El rXCHG ES-DXJ を実現
コンニチワ。こちらは冬が長い北の国です。寒い日は、家の中でパソコンをするのが最高
です。特に、マシン語をプログラムしていると時のたつのを忘れます。今はまだ入門去
ですが、そのうちアツと驚くプログラムを組んでみせます。
ところで、いつも不便に思うことがあります。それは、レジスタの xchg 命令についてです
汎用レジスタには 「XCHG reg , reg 」 命令があるのに、セグメント•レジスタにはありません
だいたい、セグメントレジスタには演算命令がありません。どう考えてもこれは不便な レジ
スタだと思いませんか?
今は次のようにしています。もっとよい方法はあるでしょうか。
PUSH
AX
MOV
AX,ES
XCHG
AX,DX
MOV
ES,AX
POP
AX
夜ふかしヒグマ(北海道)
■答--
雪がしんしんと降る中をプログラムか……。うらやましい環境だなァ。きっ
と、プログラムに疲れたら、近くの山にスキーにでも行くんでしょうね。 いい
プログラム はいい環境の もとで生まれるとよく いいます。タバコの 煙と、 ほこ
りにまみれた部屋からは、それなりのプログラムしかできないという気がしま
す。
きっと、近いうちに日本を揺るがすようなプログラムができることでしょう。
なんといっても、本人がその気になっているのが強みです。
それにしても、本当にセグメント.レジスタの XCHG 命令があってもよさそ
うです。あれば便利なことも間違いありません。
ところで、夜ふかしヒグマさんのプログラムでは PUSH / POP 命令を使って
いますが、これをうま〈使うともっと簡単になります。いわば、コロンブスの
27
卵のようなものです。
PUSH
ES
MOV
ES , DX
POP
DX
この例のように、 PUSH / POP 命令は同じレジスタでなければならないとい
う制限はありませんから、意図的に使う場合もよくあります。また、これを利
用するとセグメント.レジスタの初期化も汎用レジスタを介さずにできます。
MOV
AX,CS
- >
PUSH
CS
MOV
DS,AX
POP
DS
28
_
ント.レジスタ麵化
- ごは魔法の国です。といっても、どこにあるのか知らないかもしれません。でも、本当
w にあることだけは信じてくれると思います。だって、ポクの姉さんの友だちは地上に降
りて正義のために活躍しているそうですから……。
ここでもパソコンは盛んですが、プログラム言語はマシン語以外は使用禁止となっています。
なぜかというと、マシン語程度ができないようでは、とても魔法を使いこなすことなんてでき
ないからです。それに、ここだけの話ですけど、マシン語は魔法の呪文の練習にもなるそうで
す。ポクは、ニモニックを覚えたばかりの初心者ですから詳しくはわかりませんが、とにかく
マシン語をマスターしなければならないのです。
そこで質問です。ある時「セグメントの初期化には PUSH / POP 命令を使うといい」と知った
のですが、これしか方法がないのでしょうか?というのは、なんとなく妙な感じがするから
です。あくまでも、これはポクの感ですけど……。では、初心者のポクにわかるように教えて
ください。
ア、地上に降りた姉さんの友だちの名前はサリーっていいます。
魔法使い見習いジロー(魔法の国)
■答- .
魔法の国……。サリーちゃん……?どこかで耳にしたことはありますが、
まさか実在するとは思いませんでした。もちろん、マシン語が魔法の練習にな
るということも初耳です。なんだか、私にも魔法が覚えられそうな気がしてき
ましたが……。きっと地上では無理なんでしょうね。
さて、セグメントの初期化とは問10に示した内容だと思いますが、実はこの
方法はどちらかというと特殊な例なのです。というのは、 PUSH/POP 命令はク
ロック数がかなりかかる命令ですから、空いているレジスタがある場合には、
そのレジスタを介して間接的に初期化したほうが実行速度が速いのです。まず、
それぞれのクロック数を比較をしてみましょう。
29
※ PUSH / POP の場合
※レジスタを使った場合
PUSH CS
POP DS
MOV AX,CS
MOV DS,AX
+ 2 2
18 クロック
4 ク□ツク
ご覧の通り、トータルで14クロック違いますから、問10の初期化方法は空
いているレジスタがない場合に有効ということになります。セグメント•レジ
スタを初期化する方法としては、他にも次のような方法があります。
①メモリから口ードする
DSREG DW SEGMENT 1
MOV DSXS:DSREG
(2 M 也のレジスタとペアで口ードする
DS レジスタと16ビットレジスタをペアでロー ドする LDS 命令と、 ES レジスタと16ビッ
トレジスタを ペアと する LES 命令がある。
REGDT DD セグメント値:オフセット値
LDS SI , CS:REGDT
では、早く マシン 語を マスター して一流の魔法使いになってください。そし
て、サリーちゃんみたいに地上に降りて、今度は私に魔法を教えてくださいナ。
3 〇
_
I^QTexxj 鈴を親
/- 論島をご存じですか。そう、若者の島、ヨロン島です。沖縄が日本に返還されるまでは、
フ日本最南端の島といわれていました。
わたしの家は民宿をしています。ヨロンにはヨロン憲法(献奉)という歓迎の挨搂があって、
島に来た人はまず焼酎をなみなみと飲まされるんですよ。わたしの役目は飲むふりをして飲
ませることです。だって、次の日は学校だもん。
ここの海岸にはコンペイ糖みたいな形をした星の砂がたくさんあります。有名だから知って
ますよね。わたしは、いま「星の砂」というタイトルの Z 80 用のゲームを8086用に組み直して
います。
でも、 Z 80 にあって8086にはない命令があって困っています。それは裏レジスタへチェンジす
る EXX 命令です。こういう場合、8086ではどのようにすればよいのでししようか。
星降る乙女(与論島)
■答- •
ヨロン島の星降る乙女ちゃんの作品で「星の砂」……。もう目の前にメルへ
ンの世界が広がってきそうです。ヨロンには潮が引くと沖合いに島のように現
れる百合が浜なんていうのもあるし、夢がいっぱいですね。
でも、お酒を飲めない人にとっては、ヨロン憲法は余りにもキビシイ憲法で
す。そのわりには、毎日の宴会
は楽しかったけど……。だから、
質問にピッタリの答を教えてし
まいましょう。
まず、レジスタを左のように
対応させると、答としては次ぺ
ージのようになります。
8 ビット長レジスタ
16 ビット長レジスタ
Z80
8086
Z80
8086
A
AL
BC
CX
B
CH
DE
DX
C
CL
HL
BX
D
DH
SP
SP
E
DL
PC
IP
H
BH
IX
SI
L
BL
IY
DI
Z 80 と 8086 のレジスタの対応
31
CALL
EXX
EXX
PROC
XCHG
BXXS : REGBX
XCHG
CX . CS : REGCX
XCHG
RET
DX , CS:REGDX
EXX
ENDP
REGBX
DW
0
REGCX
DW
0
REGDX
DW
0
と、一般的にはこうなりますが、もし、 Z80 で使用していないレジスタが1
つでもあれば、メモリではなくレジスタと置き換えることも可能です。ここで
は例として Z80 のインデックス•レジスタ IY を使っていない、すなわち、8086
では DI レジスタが空いていると仮定して マクロ 定義をしてみました。
EXX MACRO
XCHG
BX,BP
XCHG
CX.DI
PUSH
ES
MOV
ES,DX
POP
DX
ENDM
余談ですが Z80 の 「EX AF,AF’」 は、フラグを無視すれば 「XCHG AL,
AH」 で置き換えが可能です。ところで、星の砂ってどうしてあんなにきれいな
星の形をしているんでしょうか。一説によると、ヨロンのあの満天に散りばめ
た星の群れから、時々はみ出して落ちてきたという話ですが、本当のことを知っ
ていたら教えてください。星降る乙女さま……。
32
_
H いてください。わたしの悩み。マシン語の便利な用法がたくさんでている本を買つたん
です。その本にはノレープ命令には、 LOOP 、 LOOPZ 、 LOOPE 、 LOOPNZ 、 LOOPNE 力《あ
ると書いてありました。早速、わたしは役立てようと思いました。
SI レジスタに、メモリ•ブロックの先頭アドレスを格納して、このメモリ•ブロックの中に〇
があるかどうかサーチせようとしたんです。
LP 001 :
CMP
BYTE PTR [ Sl ],0
INC
SI
L 00 PNZ
LP 001
JNZ
SHORIl
これが、その時のプログラムです。でも、メモリ•ブロックに0があっても、いつも最後まで
LOOP してしまうんです。このプログラムにはバグでもあるんでしようか。
悩める美人の 0 L (福岡)
■答- *
オー ッ と、美人の ol とはウレシイじゃありませんか。マシン語というのは、
蒸気機関車みたいな人間臭さがあるせいか、あまり女性には好かれませんでし
た。でも、女性がマシン語を操るというだけで、パソコンのイメージが‘ネクラ’
から‘ネアカ’に変わりそうです。
さて、このプログラムは一見すると正しいようですが、実はそこに大きな落
し穴が潜んでいます。それは、フラグというものに対する過信です。フラグレ
ジスタというレジスタは、思ったより好き嫌いの激しい性格をしています。
ここで問題となるのは、 「LOOPNZ」 の命令が実行されるまでのフラグ変化で
す。おそらく美人 0L さんは、 「INC SI」 のフラグ変化を忘れていたのでしょ
う。8086では、16ビット長の 「INC」、「DEC」 命令であってもフラダが計算結
果にしたがって変化するのです。このような間違いは、 Z80 などのマシン語か
33
ら、8086へと移行したプロフラマーの初期の段階によく現れる代表的なもので
すから注意してください。
ここで やった riNC SIJ という 作業は、 SI が 〇 でない 限り、常に ゼロフラ
ダをクリアすることになりますから、最後までループしてしまった という わけ
です。
では、どうしたらいいかというと、 CMP 命令の前で 「INC SI」 を実行すれば
よいのです。
DEC
SI
LPOOl : INC
SI
CMP
BYTE PTR [ SI ] ,0
LOOPNZ
LP 001
JNZ
SHORIl
もし、 AX、DI、ES レジスタが空いていれば、8086特有の命令を使って次の
ようにすることもできます。
MOV
DI,SI
MOV
AX,DS
MOV
ES,AX
CLD
XOR
AX , AX
REPNZ
SCASB
JNZ
SHORIl
マシン語も女性に好かれるようになると、もっともっと夢のある世界が大き
く広がるんですが . 。まずは‘悩める美人の OL’ さんの悩みを解消したこと
で、少しは未来が明るくなった気がしませんか。
34
« ^ス。おいどんは、薩摩隼人でごわす。時代の波に乗り遅れぬよう、おいどんもパソコン
を買ったでごわす。 BASIC は、ハツキリいって遅くてイライラする。やはり、時代はマ
シン語でごわすな。
おいどんは、未来を的確に見つめるため、いまあるプログラムを作っておるのだが、ある事情
でコールするたびに+ 50と一50という値を交互に返してくれるようなプロシージャが必要な
のでごわす。現在は次のようにしておるが、どうもこのプログラムはスツキリしないのでごわ
す……〇
M 0 VAX
EQU
0 B 8 H
DAT 50
PROC
DB
MOV—AX
DATKP
DW
50
CMP
AX , 50
JE
DAT 51
MOV
AX , 50
JMP
DAT 52
DAT 51 :
MOV
AX ,-50
DAT 52 :
MOV
DATKP , AX
RET
DAT 50
ENDP
(注 ) DS = CS と仮定する
ぜひ、的確な評価をしてほしいでごわす。お願いでごわす。
マシン西郷(鹿児島)
■答--
これはこれは、時代を超越したような質問でごわすな。こちらまで影響を受
けてしまいそうでごわす。
このプログラムは、確かに見るからにスッキリしませんね。プログラムを書
き換えながら使うなど、苦労の跡はうかがえるのですが、苦労がむくわれてな
35
いようです。でも、プログラムがスッキリしないと感じている点に、 マシン 語
の夜明けを感じます。
マシン語プログラムで、スッキリしないとか不格好だと感じた時は、命令の
一覧表(三の章の8086ニモニック表)を見直すと、いい知恵が浮かぶことがあ
ります。それは、マシン語を覚えたてのころは、使い慣れたニモニック以外使
わない(使えない)という傾向が強いからです。
この西郷クンも、便利な命令をまだ見落としているのです。こんな時には、
「 NEG 」 という最適の命令があるんですよ。
DAT50
PROC
MOV
AX,DATKP
NEG
AX
MOV
DATKP,AX
RET
DAT50
ENDP
DATKP
DW
50
( 注 ) NEG はメモリに対しても有効
「 NEG 」 とは 、 NEGATE (否定する、正負を反転する)の略ですが、この命
令を使えば一発で正なら負へ、負なら正へと変換してくれるのです。もちろん、
ここでの正とか負というのは、問2にあったように、あくまでもプログラムを
組む人の感覚であることを忘れないでください。一応サインフラグ上では、ビッ
卜15 (8 ビット長であればビット 7) の値で+/—を判断するようになってい
ますが……。
時計を読むのに、何時何分過ぎと読むか、何分前と読むか、それは読む人の
勝手というようなものです。では、同じような感覚で0と何かを交互に返すブ
ロシージャ、と問題を変えたらどうでしょうか。例えば、0と50を交互に返し
てくれるようなプロシージャがほしい場合です。もちろん、質問にあるような
プログラムにもどってしまうようでは、維新の夜明けは遠くなるばかりです。
36
DAT50
PROC
MOV
AX,DATKP
XOR
AX ,50
MOV
DATKP, AX
RET
DAT50
ENDP
DATKP
DW
0
(注) XOR はメモリに対しても有効
今度は論理演算 XOR です。 XOR は二度繰り返すと値が元にもどるという特
徴を利用するわけです。では、初期値を0ではな〈別の値にしたらどう変化す
るか、 XOR に対する理解を深めるためにも自分で確認してみて〈ださい。
よくわからないという人は、キチンと二進数にして演算すればいいでしょう。
ナニ、そんな簡単なこと知っていたでごわすか!!こりや、失礼したでごわす。
37
mqv 命令を減らす
ては大阪の生まれだす。手紙も電話も大阪弁以外ではしませんのや。もちろん、英語
u だって大阪なまりだす。それが、浪花のド根性と思うとんのや。
そ、そのわてが、なんとマシン語に凝ってしもたのや . 。くやしいけど、わてのパソコンか
て大阪弁は理解してくれへん。これはホンマに残念なことやで。マ、それはいいとして、わて
のマシン語というと、厶ーブ (MOV) 命令の連続なんや。
やっと、ワークエリアが自由に使えるようになったんやが、その中身を操作するたびにムー
プ、ムーブや。例えば、こんな具合いや。
MOV
AX,OKANE
SUB
AX ,2
MOV
OKANE , AX
MOV
AX,YAKSO
INC
AX
MOV
YAKSO,AX
rOKANEj とか 「 YAKSO 」 というのがワークエリアなんやけど、アドレスでいうたらお隣り
どうしやで。もっと、わての大阪弁みたいに流ちようにいかんのやろか。ア、プログラムの内
容はお金を使って薬草を買うた、という意味や……。
浪花ぼてじゃこ物語(大阪)
■答- *
英語いうたかて世界中どこでも通用するわけではあらへん。わてもイタリア
を放浪しよった時は、大阪弁使いよったで デタラメの . 。
外国人というと、みな英語を話すと思ってしまうのが島国日本人の悲しさ。
苦労して下手な英語を使っても、通じない国はたくさんあります。どうせ通じ
ないのなら、日本語でも同じこと。真剣に話すと、結構相手もわかってくれる
ようです。
その日本語でも流ちょうに話すのは難しいのに、マシン語を流ちょうに使い
たいとは驚きです。凡人には、なかなか言えないことです。
では、さっそく流ちょうでないプログラムを見てみましょう。流ちょうに見
えない原因は、アドレスをすべてダイレクトに指定しているからです。忘れな
いでください、インデックスレジスタというアドレスを示せるレジスタがある
ことを。
かりに、 「 OKANE 」 と 「 YAKSO 」 というアドレスが、番地の若い順に並ん
でいるとしましょう。一方のアドレスを指定すれば、隣りのアドレスは簡単に
わかります。流ちょうな日本語ができなくたって、隣りの家をいちいち住所で
言う人はいませんね。どこか一軒を指定すれば、あとは一軒先とか手前という
ように相対的に表現するのが普通です。
MOV SI , OFFSET OKANE
SUB WORD PTR [SI], 2
INC WORD PTR [SI + 2]
これで、プログラムに要するメモリ数は約半分になりました。気になったムー
ブ命令も1つになりました。……が、ムーブ命令の多少とプログラムの良否に
ついては、まったく関係ありません。
そのことより、メモリ中のデータを操作する場合、できるだけアドレスをレ
ジスタで指定するように心がけることが大切でしょう。ほとんどの場合、それ
だけでメモリ数/クロック数の減少につながります。
ところで、レジスタ AX は他の汎用レジスタ ( BX , CX , DX ) よりも、メモリ
からのデータの ロード、 またはデータのストアに対する クロック 数が少ないの
で、最後の 「INC WORD PTR [ SI +2]」 は、むしろ元のままの ( MOV ) 命
令を使ったプログラムの方が、実行スピードが早いくらいです。
また、関連するワークエリアのアドレスが前後に散らばっていたりする場合
にも、インデックスレジスタ ( SI / DI ) を使用するとプログラムはスッキリしま
す。もし、あなたが MASM を使っているなら、メモリのワークエリアを構造体
として宣言しておくとブログラムは、さらに見やすくなります。
どないだ。これで、マシン語も大阪弁に一歩近づいたでっしゃろ!!
39
_
_ ッボンのみなさ〜ん。お元気ですか . 。
—ワタシはおじいさんとおばあさんが日本人の日系三世です。英語名はドナルド、日本名
は拓です。だから、ドナルド•タクというわけです。もちろん、通称はドナルド•ダックです。
でも、初めて日本へ行った時‘ドナルド’って呼ばれても誰のことかサッパリわかりませんでし
た。それに、日本語でいう『マクドナルド J というお店、これも行ってみるまで何のお店かわ
かりませんでした。ヤッパリ、ワタシはアメリカ人です。
ところが、うれしいことに日本人もマシン語を使うというじゃありませんか。それならという
わけで、ワタシもマシン語を始めました。だから、まだ入門者です。そこで、ちょっと教えて
ください。
AL レジスタのビット5だけを、あるメモリにそのまま移したいのです。ビット5以外は変更
したくありません。いまは次のようにしています。
MOV
BX,OFFSET MEMRY
TEST
AL , 001000 00 B
JE
RSET 5
OR
BYTE PTR [ BX ], 001000 00 B
JMP
XSET 5
RSET 5 : AND
BYTE PTR [BX],1 皿 HUB
XSET 5 : i
ヤツパリ、こんなもんでしようか。
Donald Tack (ロサンゼルス)
■答- .
実は、私も憧れのディズニーランド(東京ではなく ロスのほうです)へ行く
前日、現地の人に明日はドナルドダックに会いたいと言ったのですが、いくら
「ドナルド」「ドナルード」「ドーナルド」と言ってもわかってもらえなかった
ことがあります。
あれを『ダーナーダック』って発音するなんて . 。『マクダーナー』という
お店も日本にはないですからね。カタカナの英語がこんなにデタラメだとは、
その時まで知りませんでした。ちなみに、私が話した現地の人というのは、一
4〇
応日本語も話せる日系三世の人だったんですが……。
こうなると、マシン語を国際語にするしか方法はなさそうです。質問にも快
く答えてしまいましょう。
まず、質問にあるプログラムは、少し手直すだけで無駄なジャンプ命令が省
けてスッキリさせることができます。
MOV
BX,OFFSET MEMRY
AND
BYTE PTR [ BX ] # 110111 11 B
TEST
AL , 001000 00 B
JE
RSET 5
OR
BYTE PTR [ BX ] ,00 10000 0 B
RSET 5 : j
これだけで十分と言えないこともありませんが、この程度のことでジャンプ
命令を使うのはカツコ悪いと感じる人もいるでしよう。そこで、 AL レジスタの
値はこわれてもいいという条件で、次のようにプログラムを組むのも一考です。
MOV
BX,OFFSET MEMRY
AND
BYTE PTR [ BX ], 110111 11 B
AND
AL , 001000 00 B
OR
BYTE PTR [ BX],AL
r なんだ、変わりばえがしないな!!」なんて思いませんでしたか。確かに、こ
の例に関してはそう言われても仕方ありません。では、もしもビット5とビッ
卜3の2つの値を移したいとなったらどうでしょうか。
最初のやり方では、プログラムが単純に倍になってしまいます。それに対し
て、二番目の方法なら各 AND 命令のオペランドを変更するだけで済みます。こ
れはメモリ数や速度に影響を与えるものではありません。
つまり、両方を知っていればプログラムに合わせて効率のいい方法を選べる
ということなのです。やはり、何事においても基本は大切ですね。
英語の基本は ABC ……、決してカタカナではなかったのです。
4J
n
シ-ジャへのジャンプ^
クの友人にパソコンを小学生の時から持っている上、すでにマシン語までマスターし
小 てしまった者がいます。ポクは、1年前やっと高校入学と同時に買ってもらいました。
そして、なんとか BASIC は彼と同レベルになりましたが、マシン語ではまだまだその友人に
かないません。そこで彼に内緒で質問します。
CALL
xxxx
RET
マシン語プログラムには、こういうケースがよくでてきます。ポクも最初はこのままでした
が、ある時コールしてからリターンするなら、 「 JMPxxxx 」 とすればいいのではと思ったので
す。どうせ、コール先の RET 命令で元のルーチンへ戻れるからです。
以来、このような場合には 「 JMPxxxx 」 としてきましたが、それで問題が起きたことは一度
もありません。でも、ポクの友人にその話をしたら、いずれダメな時も出てくると言います。
理由を聞いてもハツキリ教えてくれません。
いったい、どういう時にダメなんでしょうか。ソツと教えてください。ポクは、今でも大丈夫
だと思っています。
ドラ Q (新潟)
■答-_
友人に自慢されている様子がよくわかります。似たような経験は誰しも一度
はあるものです。でも、たったの1年でこんな鋭い疑問がわくのも、その友人
のおかげと思えばいいじゃないですか。
この問題は、それほど奥が深いのです。メモリに余裕がある場合には、入口
と出口は1つという原則を守ってプログラムを組みますから、質問のような手
法はとりませんが、このような手法でも困ることはありません。それどころか、
いったん、メモリ不足になった場合には、1箇所で1バイトの節約になります
から、こういう箇所を必死に捜すことになります。また、スピードのアップ(あ
くまでも計算上です)にもなっています。
42
では、どんな時に困るかというと、それはスタックを操作しながらプロダラ
ムが走っている場合です。例えば、メインプログラムからプロシージャ
「 AAAA 」 がコールされ、プロシージャ 「 AAAA 」 の最後でプロシージャ
rccccj がコールされているとします。
MAINP : j
AAAA: !
CCCC ::
CALL AAAA
CALL CCCC
RET
!
RET
確かに、ここで プロシージャ 「 AAAA 」 から プロシージャ 「 CCCC 」 へジャ
ンプすれば、プロシージャ「 CCCC 」 の RET 命令でメインプログラム へと もど
ります。しかし、 プロシージャ rcccc 」 の プログラムが、 条件によっては メイ
ンプログラムへ 直接リ ターンす るよう に 設計されていたらどうで しょ うか。
つまり、 プロシージャ rccccj が 「 MAINP 」 から数えて常に二段目にコー
ルされるようになって いて、 条件によってはスタックを操作(スタックポイン
夕を +2) して 「 AAAA 」 へもどらずにダイレクトに 「 MAINP 」 ヘリターン
するような場合です。もし 「JMP CCCC 」 でこのようなケースに出会うと、ス
タックが狂ってしまい 「 MAINP 」 を通り越してどこかへ暴走してしまうことに
なります。
もちろん、プログラムを作った本人がこのような作り方をしなければ問題は
ないのですが、共同で大きなプログラムを開発したり、他人のプログラムを借
用したり、あるいはシステムの内部ルーチンをコールする場合など、こういっ
た危険性はアチコチに潜んでいるのです。たとえ入口と出口は1つという原則
にそってプログラムが開発されようと、完全に守られるという保証はありませ
ん〇
具体的な例をあげてみましょう。画面上にピョンピョン跳ねて いる 小さな
ボールが1 つ あるとします。ボールは画面に散らばって いる 釘に触れると破裂
してしまいます。わかりやすくするため、設定はたったこれだけです。
プロシージャ 「 AAAA 」 はボールとすべての釘との衝突を管理するルーチン
で、ボールの動きを管理している 「 MAINP 」 からコールされています。 「 AAAA 」
では、 BX レジスタにボールの座標、 CX レジスタに釘の座標を入れ、次々と座
43
標チェックと破裂を実行するプロシージャ 「 CCCC 」 をコールします。
4-AAAA へもどる
—破裂のプログラム
< -ダ ミー
— MA 旧 P へもどる
プロシージャ 「 CCCC 」 では、ボールと釘との衝突チェックを行いますが、ひ
とつでも釘とボールが衝突していたら、その時点でボールは破裂し残りの釘と
の衝突チェックは不要になります。つまり、プロシージャ「 CCCC 」 からプロシー
ジャ 「 AAAA 」 へもどるのではなく、直接 「 MAINP 」 へもどるケースが生じ
るわけです。これを実現しているのが、破裂処理のあとにあるダミーのスタッ
ク操作です。このスタック操作が成立する前提として、スタックの条件(レべ
ル)を統一するようなプログラムが要求されているわけです。
面倒そうですが、いずれプログラムに慣れてくると、スタックを考えながら
プログラムを組むようになるのです。新潟のドラ Q 君がそうなるのも時間の問
題です。もう友人にも自慢されなくてすむでしよう。
CCCC
PROC
CMP CX,BX
JE
RET
CNRT
CNRT :
POP
RET
AX
CCCC
ENDP
AAAA
PROC
MOV
BX,BALXY
MOV
CX , KUGZ 1
CALL
CCCC
MOV
CX , KUGZ 2
CALL
CCCC
MOV
CX , KUGZ 3
CALL
CCCC
RET
AAAA
ENDP
44
_
輩は猫である。名前はまだない。猫に小判という諺はあるが、猫にコンピュータという
^諺はない。だから、猫がコンピュータに興味を持ってもおかしくはない。
……という書き出しで始まる『猫とコンピュータ』という小説を知っていますか。おそらく、
まだ誰も知らないはずです。というのは、まだ完成していないからです。私がその作者ですか
ら、それは間違いのない事実です。
実は、この猫は超能力を持った猫で、プログラマーである飼い主に、プログラムのバグや欠点
を教えるというのが話の大筋です。しかし、作者である私がプログラムの初心者なので、欠点
を直すというのが大変なことなのです。それが、小説が進行しない最大の原因となっていま
す 。
いま、小説の中のプログラマー氏が次のような2つのプログラムを組みました。その2つはほ
とんど同じ内容のプロシージャで、まん中の一部が違っているだけです。どのような助言を猫
が与えるべきでしようか。
SUBA 1
PROC
DEC AX
RET
SUBA 1
ENDP
ADDA 1
PROC
INC AX
RET
ADDA 1
ENDP
いま考えているのは、前半と後半をプロシージャとして共通化する方法ですが、そうすると前
半のプロシージャの途中でリターンしたら困りそうです。
ペンネー厶猫目漱石(愛媛)
■答-《
岡目八目ならぬ猫目八目というわけですか。しかし、猫の先生にあたる作者
がプログラムをよくわからないとなると、超能力猫からバグ猫に……。下手を
すると、化け猫小説となってしまいそうです。
そこで、質問にある修正案通りにプログラムを組んだことにして、それが超
能力猫の判断に見合うかどうか、まずチェックしてみましょう。
45
ADDA 1
PROC
CALL
HALF 1
INC
AX
CALL
HALF 2
RET
ADDA 1
ENDP
SUBA 1
PROC
CALL
HALF 1
DEC
AX
CALL
HALF 2
RET
SUBA 1
ENDP
HALF 1
PROC
RET
HALF 1
PROC
HALF 2
PROC
RET
HALF 2
ENDP
「 HALF 1」 というのが前半の共通プロシージャで、 「 HALF 2」 が後半の共通
プロシージャというわけです。一見すると、うまくまとまったような気がしま
すが、問題は「 HALF 1」 のプログラムの途中でリターンすることがある場合で
す 。
つまり 「 HALF 1」 の途中でのリターンは、それぞれ 「 ADDA 1」「 SUBA 1」
からのリターンを意味していますから、この場合 「 HALF 1」 の中で特別にス
タック操作をしてリターンしなければならないわけです。
リターンに関するスタック操作は問17にもありましたが、キチンとスタック
の状態を把握さえしていれば難しいことではありません。しかし、プログラム
の途中でかりに 「RET N 」 などとなっている場合、いったんどこかにジャン
ブしてからスタックを操作しますから、意外と面倒です。
46
さらに……、 「 HALF 1」 がプロシージャをコールしているとなると、話はま
すます複雑になります。というのは、そのプロシージャ先でスタック操作が行
われている可能性だってあるからです。
……どうやら、このままでは化け猫小説になりそうな雲行きです。もっと簡
単な手法で解決することにしましょう。それは、例の書き換えを使う方法です。
—40 H = INC AX
—48 H = DEC AX
こうすれば、プログラムを完全共有化できる上、スタックなどの余計な心配
をする必要はなくなります。プログラムが長くなればなるほど、このような書
き換えによるメモリ節約は効果を発揮してくれます。
SUBA 1 で 「MOV CS : POINT , DEC _ AX 」 実行後 ADSBl を コールし てい
ます。一見すると、そのまま ADSB 1 へと流してもよいように思えますが、
CALL 命令によって CPU 内部の命令キュウをクリアする働きも兼ねています
から、「無駄だ」などと、うっかり削ってしまわないように注意してください。
これで、めでたく『猫とコンピュータ』が完成するといいですね……。
INC_AX
EQU
40H
DEC 一 AX
EQU
48H
ADDA1
PROC
MOV
CS : POINT,INC 一 AX
CALL
ADSBl
RET
ADDA1
ENDP
SUBA1
PROC
MOV
CS: POINT,DEC_AX
CALL
ADSBl
RET
SUBA1
ENDP
ADSBl
PROC
POINT
DB
INC 一 AX
RET
ADSBl
ENDP
47
^■3 フラグで合図を送る
KI 前、新渴のドラ Q という者が質問をしたと思いますが、あれはポクの弟です。弟とポク
^は3歳離れており、ポクも去年は大学受験でした。入学と同時にパソコンを買っても
らったので、パソコンに関しては弟と同じレベルです。
ところで、先日弟がした問14への回答について、もう少し詳しく聞かせてください。あの時の
回答には、スタック操作の例としてボールと釘との衝突チェックをあげていましたが、説明と
しては理解できても現実にはピンとこないのです。
それは、ポールと釘の衝突を判定するプロシージャ rCCCCj から、どうして rMAINPj へ直
接もどるのかという疑問です。衝突チェックなんていうのは、プログラム実行時間からすれば
瞬時のできごとです。残りの釘のチェックをしたところで、実際にはなんら問題は生じないは
ずです。
それとも、直接 「 MAINP 」 へもどることにより、なにか特別なメリットでもあるのでしようか。
兄として、知りたいと思います。
下宿先のドラ Q II (山形)
■答--
ウ〜ム。そこまで突っ込んだ質問がくるとは、こちらとしても不覚にも予測
していませんでした。さすが、兄のドラ Q II さんです。
あの時の例は、あくまでもスタック操作の一例として出したのですが、今回
の質問により問題は衝突チェックのテクニックへまで発展してしまったようで
す。確かに、実行時間についてだけ考えれば、残りの釘との衝突をチェックし
たところで何の支障もありません。だとすれば、 「 MAINP 」 へ直接もどる必要
もないということになりそうです。
そこで、まずは破裂があったかどうかを「 MAINPJ へ伝達する方法について
考えてみましよう。最初に思いつくのは、破裂したことを示すワークエリアを
確保し、そのワークエリアの値を 「 MAINP 」 でチェックする方法です。
おそらく 「 MAINP 」 の書式はこのようなものになるはずです。もちろん
「 BATWK 」 に破裂フラグを立てるのはプロシージャ 「 CCCC 」 の役目です。
そして、このようなプログラムであれば 「 CCCC 」 から直接 「 MAINP 」 へもど
BATWK
DB
0
MAINP :
CALL
AAAA
MOV
AL , BATWK
OR
AL,AL
JNE
GOVER
—衝突チェック
—破裂フラグが立っていればゲームオーバ—へ
(注) DS=CS と仮定する
る必要もありません。
つまり、プロシージャ rcccc 」 は衝突があるないにかかわらず、すべての釘
とのチェックをすればいいからです。では、どのような場合に直接 「 MAINP 」
へもどったほうがいいのでしょうか。それは 「 MAINP 」 が次のようになつてい
る場合です。
MAINP : 1
CALL
AAAA
JE
GOVER
プログラムとしては、見るからにこちらのほうがスッキリしています。破裂
を示すフラグはゼロフラグですから、ワークエリア 「 BATWK 」 も不要です。
もちろん、プロシージャ 「 CCCC 」 ではダミーのスタック操作後にゼロフラグを
CCCC
PROC
CMP
BX,CX
JE
CNRT
RET
CNRT :
POP
AX
XOR
AX , AX
RET
CCCC
ENDP
— BBBB へもどる
—破裂のプログラム
—ダミー
—ゼロフラグを立てる
— MA 旧 P へもどる
49
立てなければなりませんが。
つまり、残りの釘とのチェックを省くことで、衝突の判定に利用したゼロフ
ラグをそのまま破裂フラグとして利用しているわけです。もしも、最初のよう
な書式であれば、ゼロフラグを立てる代わりに、 「 BATWK 」 に1を入れる とい
うプログラムが必要です。
今回は ゼロ フラグでしたが、このほかにも プロシージャ から プロシージャへ
の条件の引渡しには、キャリーフラグなどもよく使用されます。フラグを単に
その場の条件分岐のためだけでなく、引数代わりに活用することで、プロダラ
ムの雰囲気はかなり変化してきます。ドラ Q 兄弟にも、あるいは少しばかり差
がついてしまったかもしれません。
5〇
||
20
範囲のある比較
- f す、ーガー . 。エー 、 聞こえるあるか。どうぞ . 。
こちらは地球から遠く離れたアンドロメチヤ星雲、メソポチヤ星の外星広報担当、ルー
卜力•ダッぺ将軍ある。ヨロシクあるネ。現在、銀河太陽系惑星•地球に向け知能情報収集の
ため超能力波を送信中。地球の名誉のため答えるあるよろし……。
これまでの*倩報によれば、地球にもようやくコンピュータが発生したようであるが、まだまだ
マシン語は普及してないとのことあるね。わがメソポチヤ星は、マシン語が唯一の言語ある
が、そのレベルは不明ある。
例えば、 AL レジスタの値が5〜20の範囲にあるかどうかを調べる場合、われわれは次のよう
に話すあるネ。フラグの使い方の見本みたいあるよ。 AL レジスタがその範囲にない時は、キヤ
リーフラグを立てて結果を返すようにしているある。
CHECK
PR 0 C
CMP
AL ,5
JNB
CHENR
RET
CHENR :
CMP
AL ,21
JNB
SETCY
CLC
RET
SETCY :
STC
RET
CHECK
ENDP
地球では、どんなもんあるか。教えるよろし……ガー……。
ルートカ将軍(メソポチャ星)
■答一-《
ワッ!!
いきなり変な質問が私の頭に飛び込んできたある……。どうやら、地球人と
しての能力を調査されているみたいあるネ。これは、真剣に考えなくては……。
しかし、プログラムのレベルからすると、入門者と上級者の中間あたりをウ
口つ いている ような星のようです。というのは、結果をキャリーフラグで返す
5 /
という高級なテクニックを使っているわりには、プログラムがどうも低レベル
なのです。
確かに、キャリーフラグのセット/リセットなど、基本的な常識も知っては
います。ところが、それらのテクニックがプログラムに反映されていないので
す。少なくとも、このプログラムは次のようにするべきです。
CHECK
PROC
CMP
AL ,5
JB
CHERT
CMP
AL ,21
CMC
CHERT :
RET
CHECK
ENDP
せっかくニモニックには 「 CMC 」 というキャリーフラグを反転する命令があ
るのですから、ここで使わないという手はありません。なかなか 「 CMC 」 を使
うチャンスなんてないですからね。ここは絶好の使用例といえるでしょう。
さらに、 AL レジスタが破壊されてもいい場合には、マイナスの数値はプラス
の大きい数値と同じ(問2参照)という、マシン語数値独特の特徴が活用できます。
CHECK
PROC
SUB
AL ,5
CMP
AL ,21-5
RET
CHECK
ENDP
最初に5を引いてしまうことにより、5未満の数 (0-4) は一5〜一1、つま
り十六進数では FB H 〜 FF H となります。これは結局21以上 (5 を引〈前)の数
値ですから、一度の CMP 命令で範囲のある判定ができるわけです。
ただし、この判定ではキャリーフラグの立ち方が最初の例と反転しています。
このプログラムをコールしているほうでも、条件分岐の条件を反転させる必要
があるのは言うまでもありません。
こうしてみると、地球のマシン語レベルも国際的、いや宇宙的に通用しそう
なレベルにあるではありませんか。どうであるか、ルートカ•ダッぺ将軍……?
52
レジスタベア® i を 2 倍に
±ivj 者の名は
畑いたい 〇
、武蔵。名前が古いせいか、どうも話し方まで古くさいが、その点はご勘弁願
現代の武蔵はノ\。ソコンをこよなく愛し、マシン語を自在に操ろうと日夜キーボードを叩いて
おる。先んずれば人を制す。これも、永遠のライバル小次郎に先を越されないための知恵であ
る。
とはいえ、現代の小次郎もどこかでパソコンをいじっているに違いない。いずれマシン語で対
決する時が来るであろう。時代は違っても、武蔵が小次郎に負けることは許されぬことなの
じゃ〇
拙者はいま、対決用プログラムの中で BX,CX を ペアと する32ビット長の値を2倍にしなけ
ればならんのだが、どうもうまくいかん。どうしたものであろうか……。海が荒れよるの才。
武蔵旅情(玄海灘)
■答一- *
パソコンは人を選ばない。しかし、マシン語を話さない者には本当の心を開
かないという。1台のパソコンをめぐって、マシン語とマシン語の壮絶な戦い
が始まる……。
戦いに勝っためには、限られたニモニックの中で、最大限の工夫とヤリクリ
をしなければならないのです。勝負の世界のキビシサ、それは剣がマシン語に
変わっても永遠に変わらぬ心理です。
ということで、 BX , CX レジスタをペアとする32ビット長の値を2倍にする
のは加算命令を使えば簡単に実現できます。
ADD CX,CX
ADC BX,BX
しかし、レジスタのイ直を2倍するというのは、なにも同じレジスタ同士を加
えるだけではありませんね。そうです。左方向へシフトすればいいのです。そ
の逆に右方向へシフトすれば、レジスタの値は半分になります。
53
32 ビット
f ったキヤ
リーフラグを利用するのです。
BX . CX レジスタをペアとする32ビット長の値を2倍にする
BX . CX レジスタをペアとする32ビット長の値を1/2倍にする
たったこれだけのことですが、それぞれのシフト命令の持っている役割に注
意してください。このような答は簡単であればあるほど利用価値があるという
わけです。
でも、これのどこが対決プログラムになるんだろうか……?
ただし、残念なことに16ビットレジスタのシフト命令はあっても、
レジスタを一度にシフトする命令はありません。そこで、この出 っ(
1/で倍
SHR BXJ
RCR CXJ
SHL
CX ,1
RCL
BXJ
キヤリ—フラグ
54
閩
22
マイナスの値を1/2にする
、® いぞ、 武 蔵!!
$もはや、拙者の対決プログラムは完成しておる。あとは武蔵の到着を待つばかりなのだ
が、拙者は到着が遅いからといってイライラしたりはせぬ。拙者だって、過去の話くらいは
知っておるからな。
それにしても遅い……。まさか逃げたのでは。とりあえず、最後のプログラムチェックだけで
もしておこうか。
ヤヤヤッ!!暴走してしまった。まだ、プログラムにバグがあるようだ。どうもデータを半分
にする部分がマズいようだ。本に載っていたのを、そのまま信用して使ってみたのだが、あの
本にはバグでもあるのかも知れぬ……。
拙者の場合、マイナスのデータを半分にしただけなのだが、たしかマイナスとはプログラムを
組む者が数値をどう見なすかという問題のはずだ。だから、そこにバグがあるとは思えぬし
ちなみに、そのマイナスのデータは AX レジスタと DX レジスタをペアとする値についてであ
るが、次のように本の通りにしている。ウ〜ム……わからん。
AX , DX レジスタをペアとする32ビット長の値を1/2にする
SHR
AX ,1
RCR
DX ,1
もしかすると、あの本は武蔵の謀略本なのだろうか……。
ツバメ小次郎(巌流島)
■答--
すでに武蔵と小次郎の心理戦は始まっているようです。ただ、どちらもプロ
グラムが 未完と いうの が気になりますが……。それにしても、あの巌流島でマ
シン語とマシン語が火花を散らすなんて、ワクワクしてしまいます。
さて、このバグは謀略によるものなどではありません。数値をマイナスと見
なすか、プラスと見なすか、それは確かにプログラムを組む人の勝手です。し
かし、数値を1/2にする場合はプラス/マイナスをキチンと区別しなければなり
ません。問21の方法は、あくまでも数値をプラスと見なしている場合に有効な
55
のです (2 倍にするほうはプラス/マイナスを問わない)。というのは、マイナ
スと見なした数値の割り算(割る数= 2以上の場合)では、必ず最上位ビットニ
1としなければならないからです。わかりにくいので、具体的な例で確認して
みましよう。
AL =11111100 B を
AL =11111100 B を
AL =00000100 B を
252と見なした場合:
— 4 と見なした場合:
4と見なした場合:
AL =00000100 B を一252と見なした場合
AL +2 二126 (01111110 B )
AL +2= —2 (11111110 B )
AL +2= 2 (00000010 B )
AL +2 ニー 126 (10000010 B )
したがって、数値を常にマイナスと考えるのであれば、1/2したあとで最上位
ビットを1にするか、最初に rsTcj としてキャリーが最上位ビットに入るよ
うに ローテー トすればいいわけです。しかし、数値のプラス/マイナスをサイ
ンフラグ(最上位ビット)に従って判断しようという場合は、最上位ビットの
値が1/2後もそのままになるようにしなければなりません。
符号付杏の1/2計算
キヤ! J ーフラグ
こうすれば、一128〜 127(1 バイトの場合)、一 32768〜32767 ( 2 バイトの場合)
の数値をプラス/マイナスを問わずに1/2にシフト演算できます。そして、マシ
ン語にはまさにこのための命令 ( SAR 命令)が最初から用意されているので
す。つまり、プログラムを次のように訂正することで、問題のバグからは解放
されるでしょう。
56
AX . DX レジスタをペアとする 32 ビツト長の値を1/2にする
SAR
AXJ
RCR
DXJ
どうやら、武蔵も小次郎も問題が解決した模様です。私はミーハーですから、
マシン語とマシン語の凄惨な対決を早くテレビで見たいものです。
57
23
かけ算を分解して高速化その 1
r Q 2 メーター、 CQ 2 メーター……。どなたか応答願います。こちらは難破船であります。
^ 現在地不明 0 乗務員1名 0
初のパソコンによる自動操舵システム実験のため、栄光の出港をしてからどのぐらいの時が
たったのでしょう。残された電源は太陽電池だけとなり、日没ともに自動操舟它システムは波ま
かせとなってしまいます。
おまけに、本船のパソコンによる計算ルーチンにはバグがあったのです。ソースリストを見る
と、かけ算ルーチンが空白のままなのです。おそらく、プログラマー氏があとから書くつもり
だったのでしよう。コメントとして……、
BX 二 BXX 144
と、なっていました。これは、 BX レジスタの値を144倍するというような意味のはずです。で
も、それ以上はわかりません。どなたか、このかけ算ルーチンをマシン語で作ってください。
このままでは、いずれ幽霊船になってしまいます。
こちらのコールサインは fJJlVRQj です
難破船長パフェ(太平洋)
■答-_
「 JJ 1 VRQ 」 ……?
ち、ちょっと、そりゃ私のコールサインですゾ。まだ一度も使ったことがな
いのに、どうしてそんなところに……。難破船にナンパされてしまった!?
これは、真剣になってコールサインを取りもどさなければいけません。ニモ
ニックの一覧表(インストラクション表)には、かけ算の命令があります。し
かしながら ( MUL ) や ( IMUL ) では使用されるレジスタが固定されています
から、そこのところを注意して使わないと、バグを生じることになります。
MOV
AX ,144
MUL
BX
MOV
BX,AX
58
これが、もっとも単純に考えられるかけ算です。ここで、この計算結果が AX
レジスタと DX レジスタに帰されることに注意してください。
ところで、これでも正しい結果は得られますが、 ( MUL ) や ( IMUL ) を使用
したかけ算では、実行クロック数がかなり長くなってしまいます。
早い話、これは実行スピードが遅いということです。そこで、144という数字
を次のように分解します。
144 = 2X2X2X2 + 2X2X2X2X2X2X2
レジスタの値を2倍にするのは簡単です。それを繰り返せば、2倍が4倍、
4倍が8倍と、ガマの油売りの前口上みたいに倍々にふくらんでいきます。こ
れをプログラムで実行するのです。
— 2 倍
— 4 倍
— 8 倍
— 16倍
— AX =16 倍した BX の値
— 32 倍
— 64 倍
—128倍
— 144 倍 (128 倍+16倍)
かける数の決まったかけ算は、このように2のべき乗の和に分解してから計
算すると、実行時間が大幅に短縮します。この効果は、かけ算をする回数が増
えれば増えるほど大きく現れてきます。
では、早くプログラムを直して、 「 JJ 1 VRQ 」 を返してください。
SHL
BX ,1
SHL
BX ,1
SHL
BX ,1
SHL
BX ,1
MOV
AX,BX
SHI _
BX ,1
SHL
BX ,1
SHL
BX ,1
ADD
BX , AX
59
3E
24
かけ算を分解して高速化その 2
dtp 能力者……。信じられないかもしれませんが、ポクは超能力者です。テレビで有名なス
ブーン折りができるのです。
ただ、まだ超能力が弱いのでスプーンを1本折るのに3時間はかかります。それに、その間は
スプーンを撫でながらズーッと念を入れなければならないので、とにかく非常に頭が疲れま
す0
そこで考えたのが、この念をパソコンにさせるということです。つまり、ポクがスプーンを折
ろうとしている時に考えていることを、パソコンにそのままやらせればスプーンが折れるは
ずだと思うのです。
とりあえず、その準備プログラムとして必要なのが、 ALXOAO „ の値を DI レジスタに入れると
いうかけ算プログラムです。現在は次のようにしています。
AXBHL :
MOV
AH ,0 A 0 H
MUL
AH
MOV
DI,AX
RET
かけ算としては平凡なプログラムと思いますが、もう少し速度を速める方法はないもので
しょうか。なんとかして超能カパソコンを実現したいのです……。
エスパー魔脳(宮崎)
■答--
超能力者も大変そうです。そんなに苦労しなくとも、両手を使えばスプーン
折りくらい簡単に実現できるのに……。
どうせ超能力を使うなら、スプーンやフォークを割箸のようにタテに割ると
か、普通の人にできないことをやってもらいたいものです。どうして超能力者
はスプーンの首ばかりを折ろうとするのでしようか。
……という疑問は別にして、このパソコンによる超能力はすごく楽しみです。
本当に成功してもらいたいものです。
さて、この質問の例でも、実行速度を上げることは可能です。2のべき乗の
和の例は問23でやりましたから、ここでは、10 0 H の倍数の和に分解する例を示
しておきましょう。
6〇
ALX80 H = (ALX100 H )+ 2
ALX280 h = (ALX100 h ) X 2+(ALX100 h )+2
AX 280
PROC
MOV
AH , AL
XOR
AL , AL
MOV
Dl , AX
SHL
DIJ
SHR
AX ,1
ADD
Dl , AX
RET
AX 280
ENDP
ALXOAO h = (ALX100 h ) + 2 +((ALX100 h ) + 2) + 2 + 2
3
2
2
2
2
3
16 クロック
AX 0 A 0
PROC
MOV
AH , AL
XOR
AL , AL
SHR
AX ,1
MOV
Dl , AX
SHR
AXJ
SHR
AX ,1
ADD
Dl , AX
RET
AX 0 A 0
ENDP
AX 080
PROC
MOV
AH , AL
XOR
AL , AL
SHR
AX ,1
MOV
Dl , AX
RET
AX 080
ENDP
ALXIOOh
AX 100
PROC
MOV
AH # AL
XOR
AL , AL
MOV
Dl , AX
RET
AX 100
ENDP
この例ではトータルで 16 クロックですから、実に、 60 クロックもの節約とな
ります。しかし、よほど速度を追求しているのでなければ、ロジックを考える
6 i
のに時間を取られるよりも、すなおに用意されている命令を使ったほうが得策
かもしれません。
もし超能カパソコンが実現したら、ぜひそれでスプーンを縦に割って〈ださ
い。首折りスプーンは、もう飽きましたので . 0
62
3E
25
CLD と STD
たしはコンピュータ占い師 マーサ •カーイといいます。実は、コンピュータ占いと いい
n ノましても、これまでのものはほとんどがイカサマでした。あえてネタをばらしてしまい
ますと、最初にインプットした占いデータを、ただ順番に出していただけなのです。
わたしは、職業がら女装をしていますが、本当は男性です。これも一種のイカサマなのですが、
このほうがなんとなく神秘的に見えるのです。
ところが、先日イカサマを見破られてしまったのです。アラ、女装のほうではなくプログラム
のほうですワ。ホホホ……。そこで、これからは本格的にコンピュータ占いをプログラム化し
ようと思い、覚えかけのマシン語でプログラムを組み始めました。
でも、データをブロック転送する際に、時々データがメチャクチャになってしまうことがある
のです。そのブロック転送は、5000„〜5 FFF „ 番地の内容を5100„番地へ転送するという簡単な
ものです。
CLD
MOV
SI , 5000 H
MOV
DI , 510 OH
MOV
CX , 800 H
MOV
AX,DS
MOV
ES,AX
REP
MOVSW
転送方向 +、 SI レジスタに5000„番地をセット、 DI レジスタに転送先をセット、セグメントは
同じデータ•セグメント内、そして CX レジスタには転送ワード数をセットしています。どこ
も悪いところはないはずです。こればかりは占うこともできず、困ってしまいますわ、ホント。
ニューハーフ占い師マーサ(東京)
■答- .
こういう丁寧な質問をいただきますと、こちらまで女装した気分になってし
まいそうですわ、オホホホ 。
なんだか、おかしな空気が漂いだしたようです。このままでは、まともな回
答ができなくなりますので、失礼ですが相手を見ないようにして答えることに
します。
63
このブロック転送は、一見するとなんのバグもないように見えます。特に、
バグがないと思ってしまうと、長いこと悩むことになるほどです。
しかし、ブロック転送において、転送するデータのあるアドレスとその転送
先が重なっている場合は、データのディレクション•フラグ(転送方向を示す
フラグ)をキチンと使い分けなければなりません。今回の場合も、このままで
は500 0 H 番地の内容が510 0 H 番地に転送された時点で、まだ転送し終えていない
510 0 H 番地の内容が消えてしまっているのです。
では、どのようにディレクシヨン•フラグを使い分けるのか、図によって確
認してみましょう。
STD 命令(アドレスの大きい方から順次転送していく)
アドレス® アドレス®
転送先がオリジナルのデータと重ならない場合、一般には+方向とし 、 CLD
命令でデイレクション•フラグを0クリアします。それは、いちいち転送デー
夕のエンドアドレスを計算しなくて済むからです。そのせいでしようか、つい
つい一方向というのは忘れられがちな存在です。果ては、プログラムの先頭で
CLD を実行しておいて、ストリング命令を使うたびに、いちいちデイレクショ
ン•フラグを〇クリアせずにすむようにプログラムを組む場合もあるくらいで
す。しかし、天災とバグは忘れたころにやってくる。それを忘れないでくださ
い。
64
STD
MOV
SL 5 FFEH
MOV
DI ,60 FEH
MOV
CX ,800 H
MOV
AX,DS
MOV
ES,AX
REP
MOVSW
これで、ブロック転送は完璧に行われるはずですわ、オホホホ . 。しまつ
た、また相手の顔を見てしまったわ。ワワワ……。
65
||
26
CMP 命令でのジャンプ
^たしはナース。つまり看護婦さんです。でも、本当をいうとまだ看護婦見習いなんです。
^看護婦さんっていうと、白衣の天使なんて憧れる人もいますけど、実際はすごく大変な
仕事です。
それはさておき、わたしは看護学勉強のためパソコンを活用しようと思っています。でも、そ
のためのソフトなど市販されていませんから、プログラムも全部自分で組まなければならな
いのです。プログラムはマシン語を使っていますが、不慣れのためバグがないということしか
自信はありません。
ここに、 AL レジスタの値 (1 〜 5) によって5箇所に分かれるようなプログラムがあります。
バグはないと思いますが、誰でもこう組むものでしょうか。
CMP
AL ,1
JE
LABEL 1
CMP
AL ,2
JE
LABEL 2
CMP
AL ,3
JE
LABEL 3
CMP
AL ,4
JE
LABEL 4
LABEL 5 : :
せめてプログラムだけでも見習いの肩書きが取れるとうれしいのですが。未熟なわたしのプ
ログラムを、どうぞよろしくお願いします。
ホワイトエンジェル(佐賀)
■答 --《
ナース……。なんと美しい言葉のひびき。これでは、白衣の天使に憧れて、
無理にヶガをする人が続出しそうです。ついでに、マシン語のバグを治療して
くれるような看護婦さんがいると、マシン語がもっともっと広がるのですが
それにしても、バグが出ないだけでは満足せず、さらに上を目指すというファ
イトはこちらが見習いたいほどです。
66
実は、このようなプログラムは初心者がよく作ります。しかも、プログラム
としてはバグはありませんから、このままズルズルと中級者になってしまうこ
とも少なくないようです。しかし、条件分岐というのはプログラムの重要な拠
点ですから、できるだけシンプルに、そして素早く分岐させることが大切です。
この例は、そういう意味では初歩の条件分岐といえるでしょう。ここでは分
岐の条件に ゼロ フラグだけしか使用していませんが、せっかく CMP 命令を実
行したのですから、他のフラグも活用したいものです。
CMP
AL ,2
儿
LABEL 1
JE
LABEL 2
CMP
AL ,4
JL
LABEL 3
JE
LABEL 4
LABEL 5 : ::
CMP 命令を使う回数が4回から2回になりました。とりあえず、この程度の
条件分岐ではこんなものでしょうが、分岐テクニックにはまだまだ種類があり
ます。プログラムのレベルが上がるにつれ、分岐のレベルも合わせて上げてい
かないと、プログラムが条件分岐の山になってしまいます。
そんな時にこそ マシン 語専用のやさしい看護婦さんがいてほしい、と多くの
孤独な プログラマーは 願っているのです。
67
閩
27
テーブルを利用したジャンプ
yU 話その 1 :ポクの友人は、50 メートル競泳を見て「あれは身長競争だ」と言い張ってい
J る。ワケを聞くと「だって、身長50メートルの人間なら飛び込むだけでゴールだ」……。
くだらない……なんて言わないでください。こんな小話を作るのが、わが校自慢の小話クラブ
です。すでに、名作と自称するものがかなりあります。でも、大変なのはそれを管理すること
です。とはいえ、そこは高校のクラブです。なんと、名作小話をパソコンで管理することにな っ
たのです。
……ということで、プログラマーはバソコン所有者というだけの理由でポクの役目となりま
した。もちろん、カツコつけてマシン語でプログラムを組んでいます。
いま、〇〜99までの小話に簡単なアニメをつけようとしています。そのため、小話の番号別に
それぞれのルーチンへジャンプさせなければなりません。
CMP
AX ,1
JB
ANIOO
JE
ANI 01
CMP
AX , 3
JB
ANI 02
JE
ANI 03
こんな感じで各アニメ処理ルーチンへジヤンプさせようとしていますが、どんなもんでしょ
うか。小話同様、名作と言われるようなプログラムにしたいと思います。
クラブ小話(和歌山)
■答--
同じような小話をひとつ……。
食事中に、母が肥満ぎみの父に向かって「理想の体重は身長から11〇を引い
た値よ」と言った。それを聞いていた小学1年生の息子が、突然食べるのをや
めた。ちなみに、息子の身長は110 cm だった……。
クラブ小話……なんだか、銀座のクラブと間違えそうな名前ですが、一応は
68
高校のクラブと信じておきましょう。でも、この質問には銀座のクラブ「小話」
のほうが解決しやすいのです。というのは、テーブルを使うからです???
もちろん、ここでいうテーブルとはジャンプ用テーブルのことです。とりあ
えず、サンプルとしてテーブルには10のジャンプ先を用意してみました。
TABLE
DW
ANI00, ANI01,ANI 02 , ANI03 , ANI04
DW
ANI05, ANI 06 , ANI 07, ANI 08 , ANI 09
ATJMP :
MOV
BX,OFFSET TABLE
ADD
BX,AX
ADD
BX,AX
JMP
CS: [BX]
これが、テーブルジャンプの一般的な用法です。ジャンプ先を増やすには、
このテーブルにジャンプ先を追加するだけです。プログラムも短くて済む上、
どのルーチンへジャンプするのも実行時間が変わらないというのが特徴です。
さて、プログラムの最後に 「JMP CS :[ BX ]」 という命令があります。ラべ
ル参照の場合 JMP 命令は相対ジャンプですが、この場合には CS : [ BX ] に格納
されているアドレスへとジャンプしてくれます。また 、 DS = CS であれば、セダ
メント•才ーバーライド•プリフィックス ( CS :)は省いてください。
69
3E
28
-度の CMP 鈴で 5 つの麵断
y — 、忙しい忙しい。とにかく、この日は忙しい……。
ァ わしか、わしはサンタクロースじやよ。毎年、12月24日の夜には世界中の子供たちに
プレゼントを配らなければならないのじや。そして、いつものことじやが悩むのは配る順序に
ついてじや。下手をすると夜が明けてしまうからな。
そこで、最近はコンピュータを導入して合理化を図っておるのじや。「エーッ!!」と驚く人もい
るかもしれないが、このプログラム次第でわしの真価が問われるのじやから、気合いも入ろう
というもの。
いま、ここに5種類のプレゼントが用意されているとしよう。子供たちは、サンタ•プレゼン
卜方程式により、皆ある数値を持っておる。そして、その値によりどのプレゼントがもらえる
かが決まるようになっておるのだ。
その値とは、0、1、2〜 7 F h 、80 h 、81 h 〜 FF h の5種類で、ここからそれぞれのプレゼントルー
チンヘとジャンプさせるわけじや。テーブルを作ってジャンプさせるには不便だし、やっぱり
CMP 命令で1つひとつ分岐させるしか手はないかのう……。
とにかく、この条件分岐は何度も使用するので、できるだけ速く分岐させたいというのが、わ
しの希望じや。
サンタ日本代理人 • 黒須三太(富士山)
■答- .
サンタの 世界にも コンピュータが 入り込んでいるとは、正直のところ驚かず
にはいられません。そして、ここでも要求されているのはスピードです。まさ
に、スピードを制す者は世界を制すという感じです。
ちなみに、質問の内容をプログラムにすると次のようになっているのでしよ
うか0
CMP
ALJ
JB
SANTO
JZ
SANT 1
CMP
AU 80 H
JB
SANT 2
JZ
SANT 3
SANT 4 :
1
7〇
これでも悪いということはありません。どちらかというと、非常に一般的と
いえるでしよう。しかし、ここはひとつ0、1、2〜 7 F h 、80 h 、81 h 〜 FFh という、
条件分岐のもとになっている値に注目してみたいのです。
この値が偶然に付けられたのか、それとも特別な意図があって付けられたの
かは不明ですが、一度の CMP 命令で5つの判定ができる実に有効な数値なの
です。では、それぞれの値について、 rCMP AL,1」 によるフラグの変化を示
してみます。
サイン
ゼロ
才ーバー
フロー
キャリー
0
1(NG)
0(NZ)
0(NV)
1(CY)
1
0(PL)
1(ZR)
0(NV)
0(NC)
2〜 7F h
0(PL)
0(NZ)
O(NV)
0(NC)
80 h
0(PL)
0(NZ)
l(OV)
0(NC)
81 h 〜 FF h
1(NG)
0(NZ)
0(NV)
0(NC)
どうですか。4つのフラグをうまく利用すれば、一回の CMP 命令ですベての
分岐先へジャンプできそうですね。ただし、分岐の順序を間違えると、せっか
く変化してくれたフラグが役に立ちません。次の例を参考に、注意してジャン
プさせてください。
CMP
AL ,1
JB
SANTO
JZ
SANT 1
JG
SANT 2
JO
SANT 3
SANT 4 :
!
たった2バイト、4クロックの節約にしかなりませんが、要はその心意気が
大切なのです。10万回実行すれば、40万クロックの節約になるのですから。さ
らに、この分岐に優先順位(分岐する度合が多い方を先に分岐させる)をつけ
るところまで気を配れるようになると、スピード重視も本物です。もちろん、
その場合でも先のフラグ変化表を確認するのは当然ですが……。
せっかくあるフラグですから、数値を特に連続させなくてもいい場合は、こ
のサンタ的分岐法を大いに活用しましょう。
72
^ _
^^9 のぁるジャンプ
j / は、俗に団塊の世代といわれる中年のオッサンです。特にこれといった趣味はありませ
^んが、まだまだ若いモンには負けるかという気持ちで、パソコンなども頑張ってやって
おります。
趣味はないと書きましたが、実は趣味に近いような形で学生のころから続けていることがあ
ります。それは献血です。献血回数は、今のところ48回ですが、目標は100回を超えることで
す。
献血をすると、しばらくして血液の分析結果が送られてきますが、私はこのデータを パソコン
にインプットして健康管理に役立てています。いま、 AL レジスタの値(0、1、2〜 7 F h 、80 h 、
81 h 〜 FF h ) によって条件分岐するプログラムがあるのですが、ジャンプ先ではすべて AL レジ
スタの値を8にしなければなりません。
現在のプログラムを簡単に書いてみますが、なぜか無駄があるような気がします。
CMP
AL ,1
JB
PROGO
JZ
PROG 1
JG
PROG 2
JO
PROG 3
PROG 4 : MOV
AL ,8
以下 、 PROG 〇 〜 PROG 4すべて 「MOV AL , 8」で始まります。無駄があるかどうか、そして
改良できるかどうか見てください。
中年べビー(兵庫)
■答-_
同じようなタイプの人間は、アチコチにいるものです。私も、今では献血は
趣味みたいなもので、血を抜いてもらうと気分が スッ キリするほどです。それ
に、あのチクリと射された瞬間の痛みは、慣れると快感ですからね……? ? ?
ところで最近のニュ ース によると、献血された血液が無駄になることもある
そうですが、このプログラムにも想像通り無駄があります。それが、すべての
ジャンプ先にある 「MOV AL ,8」 であるということは、誰でも簡単に想像が
73
つくでしょう。しかし、そんな簡単なことでも、いざ解決しようとすると、す
ぐには名案が浮かばないかもしれません。あるいは、そんなことは気にしない
という人もいるでしょう。
でも、この本を読んだからには、ブログラムの無駄は省くようにしてもらわ
なければなりません。
CMP
ALJ
MOV
ALJ
JB
PROG 0
JZ
PR 0 G 1
JG
PR 0 G 2
JO
PR 0 G 3
PR 0 G 4 :
!
これで、ジャンプ先では 「MOV AL ,8 J をする必要がなくなったわけです。
この例のように、 CMP 命令と、それに対応するジャンプ命令との間に MOV 命
令のようなフラグに対して全く影響を与えない命令を挿入することがありま
す。また、ジャンプ命令がキャリーだけをチェックしてジャンプするのであれ
ば、 INC / DEC のようにキャリーフラグに影響を与えない命令を挿入すること
も可能です。
プログラムを組んでいると、このような局面にはよく出会いますから、覚え
ておくと便利です。もっとも、 CMP 命令とジャンプ命令の間が、いたずらに長
くなるのも、見やすさの点で問題があるとはいえますが。
74
閩
30
スタックを利用したジャンプ
ップステップジャンプで、こちらは南海の孤島で孤独な生活を送っているナゾの漂流
ハ、 者です。電気もない、ガスもない、水道もない、ナイナイずくしの中で、唯一の楽しみ
は頭を使った「想像マシン語」です。
時間だけはタップリとあるので、そのうち「想像マシン語」による「想像ゲーム」ができるは
ずです。でも、「想像デバッグ」を想像するだけでメゲそうです。
最近、覚えたばかりのテーブルジャンプを重宝して使っていますが、 BX も SI も DI も使用中
のルーチンがあります。だから 、 「JMP [ BX ] J も 「JMP [ SU 」 も 「JMP [ DI ] J もできませ
ん。 ES レジスタは空いてるのですが、なんとか方法はないものでしょうか。
半魚人(沖の鳥島)
■答-_
ち、ちょっと沖の鳥島といったら、少し前に話題になった水没寸前の岩じゃ
ないですか。どうやって、そんな島へ……!?
「想像マシン語」による「想像ゲーム」というのは初耳です。それが完成し
た時には、本物の人間コンピュータの誕生として大ニュースになるでしょう。
テーブルを用いてジャンプするのに 、 「JMP [ BX ]」 も 「JMP [ SI ]」 も 「JMP
[ DI ] J も使えないということですが、メモリの参照として BP レジスタの存在
を忘れているようです。ただし、 BP レジスタのメモリ参照では、セグメントと
して、暗黙に SS レジスタの値が使われますから、セグメント•オーバーライ
ド•プリフィックス命令の ( DS :) を忘れないようにしてください。また、メモ
リ参照のジャンプに限らず、レジスタにジャンプ先を格納してジャンプする方
法もお忘れなく。テーブルジャンプの例としては、これらのジャンプのほかに
PUSH 命令と RET 命令を組み合わせて行うこともできます。これは詰将棋で
いうなら、ちよつとヒネった一手詰めといったところです。問27を例にしてプ
ログラムを組んでみましょう。
75
ATJMP : PUSH
BX
MOV
BX,OFFSET TABLE
ADD
BX,AX
ADD
BX,AX
MOV
ES ; CS :[ BX ]
POP
BX
PUSH
ES
RET
fJMP CS : [ES]J を実現するため
ATJMP : MOV
ES,BX
MOV
BX,OFFSET TABLE
ADD
BX,AX
ADD
BX,AX
PUSH
CS : [ BX ]
MOV
BX,ES
RET
—JMP CS:[BX] を実現するため
これはスタック操作の一種なのですが、どちらもスタックへジャンプ先アド
レスを格納して、 RET 命令によりそのアドレスにもどるようにジャンプしてい
ます。条件としては、 ES レジスタを破壊してもよいということですから、いず
れにしても、 ES レジスタの使い方が鍵になってきます。
第一の例では、ジャンプ先をスタックに入れるために使っています。そして、
二番目の例では、 ES を BX レジスタの保存用に使うことによって、 BX レジス
夕を自由に使ってしまおうというわけです。
これらのテクニックを使うと、けっこう色々な形のジャンプができそうです
ね。ではそろそろ、救援船にジャンプしたらどうですか。天才半魚人さん!!
76
mi_
□ j + L 画ってスバラシィですね。映画を見るたびにそう思わずにはいられません。涙と笑いを
^誘いながら、夢と感動を与えてくれるのです。そして、映画館から外へ出た時の太陽の
まぶしさと現実の鼓動、このギャップはテレビでは絶対に味わえないものです。
ところで、映画にはよく実在する町がでてきます。そして、映画の町こそが本物の町のような
錯覚を覚えます。でも、日本にはカサだけを売っている傘屋さんなんてあるでしょうか。私は
見たことがありません。
それなのに、 r シェルブールの雨傘』の舞台は傘屋さんです。もし実在するなら、あんな町の
あんなお店で傘を買ってみたい……。
そんなことを考えながら、プログラムを組むのが私の楽しみです。いま、 AL レジスタにはビッ
卜別に意味を持たせた値が入っています。つまり、8種類のフラグになって いる わけですが、
これをビット別に各ルーチンへジヤンプさせたいのです。
—ビット0 =1なら PROG 0 へ
―ビット1=1なら PROG 1 へ
トビット2=1なら PROG 2 へ
―ビット3=1なら PROG 3 へ
—ビット4=1なら PROG 4 へ
トビット5=1なら PROG 5 へ
—ビット6=1なら PROG 6 へ
—ビット7=1なら PROG 7 へ
ジャンプの優先権はビット0から順番に低くなっていきます。そして、このようにビット別に
ジャンプをさせるケースが数箇所あります。こういう場合はテーブルを利用したジャンプは
無理でしようか。
喫茶シ: E ルブール(長崎)
MAINP : ROR
AL ,1
JB
PROGO
ROR
AL ,1
JB
PROGl
ROR
AL ,1
JB
PR 0 G 2
ROR
AL ,1
JB
PROG 3
ROR
AL ,1
JB
PROG 4
ROR
AL ,1
JB
PR 0 G 5
ROR
AL ,1
JB
PROG 6
ROR
AL ,1
JB
PROG 7
RET
77
■答- •
シェルブールとはどんな町なのだろう。町には音楽があふれ、人々は色とり
どりの傘をさしながら歩いている……。
『シェルブールの雨傘』を見た人ならそう思って当然ですよね。私も、その
美しさに憧れて、わざわざシェルブールまで行ってきました。できたら、おみ
やげに傘でも買おうと思いながら……。
小さな港町には、にぎわいも音楽も傘屋もありませんでした。観光客もいな
い、ただの田舍町です。ひょっとすると会えるかも、と思ったカトリーヌ•ド
ヌーブ……いるわけがありません。
でも、なぜかホッとしました。みやげもの屋なんてあったらガックリきたで
しょう。ただの町だからこそ、シェルブールは永遠にすばらしいのです。少し
古い情報ですが、今でもそんな素朴な町だと信じています。
さて、このようなプログラムでもテーブルによるジャンプは可能です。
TABLE
DW
PROGO,PROG1 ,PROG2,PROG3
DW
PR0G4, PR0G5, PR0G6, PR0G7
BTJMP :
MOV
BX,OFFSET TABLE
JUMP8 :
MOV
CX ,8
JMP 8 L :
ROR
AL ,1
JNB
NTJMP
JMP
CS: [BX]
NTJMP :
ADD
BX,2
LOOP
JMP8L
RET
一見すると、これは質問にあったプログラムより複雑で、時間もメモリも余
計に消費しそうな感じがするでしょう。それは事実であり、あえてこのように
する必要がない場合も多いかもしれません。
しかし、このプログラムの特徴は、複数のテーブルがあってもプログラムを
共通して使用できる ( JUMP 8 以下)という点にあります。また、ジャンプ先を
テーブル上で管理できるので、変更やデバッダが非常に楽になります。
七色の雨傘ならぬ、八色のテーブルジャンプとして活用しましょう。
78
琶
32
フラグ以外の条件ジャンプ
X /は、いまだかつて「ウソとホラと坊主の頭はゆったことがない」マ界党公認の大政治家
私 ……岩内保羅夫(いわないほらお)でございます。政治家は「ウソつき、ホラふき、芸
のうち」が当然でありますが、私はホラを言わない岩内保羅夫でございます。次回のマ界選挙
で当選した暁には、マシン語を世界の公用語にしマ界の発展に寄与する所存でございます。
実は、ある宴会の席上、酔った勢いでついつい「フラグを見ないでゼロチェックをしてみせる」
などと言ってしまったのですが、ハッと気付いた時には……ア〜レマ「遅かりし由良之助」で
す。ホラを言わないどころか、私の口からはホラ、ホラ、ホラ……ホラの大連発です。
せめて、マシン語に関することだけでもホラじゃないようにしたいのですが、やっぱり無理で
すかね ェ。 もし、ここで助けてくれたなら、当選の暁にはこの本を百万部ほど買い取ってあげ
ます。それから、私がこれから売りだそうとしているホラ止めの薬「ホライワン」を百年分さ
しあげます。どうぞ、よろしくお願いします。
岩内保羅夫(マ界党)
■答- •
どうもホラどころか坊主の頭までゆったことがありそうな雰囲気ですが、と
りあえずマシン語についてだけはホラ吹きの汚名が晴れそうです。
ジャンプ命令をよく調べてみると、その中に 「 JCXZ 」 という命令があります。
このジャンプ命令はゼロフラグをチェックしてジャンプするのではなく 、 CX
レジスタが0であればジャンプするという命令です。したがって、事前にゼロ
かどうかをフラグに反映させる命令を実行する必要がないのです。
例えば、 SI レジスタで示されるメモリ内容がゼロの時にジャンプさせたい場
合、メモリの値を CX へ代入するだけで、この命令が使えるのです。
CMP 命令によるメモリの 0 チェック
CMP WORDPTR [Sl],0 15 クロック ( 3 バイト)
JZ 氺氺氺氺
79
JCXZ 命令によるメモリの 0 チェック
MOV
CX,[SI]
JCXZ
氺氺氺 *
13 クロック ( 2 バイト)
メモリに対して INC / DEC を使うこともできますが、これは実行速度、使用
メモリ数ともに効率悪くなってしまいます。また、 AND 、 OR 、 XOR 、 TEST 、
ADD 、 SUB 命令による 0 チェックも可能ですが、やはり CMP 命令を使ったほ
うが有利です。
その点、この JCXZ 命令は CX レジスタへチェックしたい値を代入するだけ
ですから、最も効率よく目的を果たすことができます。割り算をする時やセダ
メントレジスタの0チェックにも使えますから、うまく応用するといいでしよ
う 。
ということで、マシン語のホラは解消されましたが、例の百万部の件やホラ
止めの薬についてはアテにしないで期待することにします。
8 〇
loop ^oym
れ おみゃ一、ナーゴヤいうたらエーところだでヨー。きしめんはウミャーし、ういろうも
ウミャーし、大阪と東京のエーところを取り入れた日本の中心都市だでヨ。それに、もうひと
つの名物はパチンコ屋だで。
実は、わしゃパチンコが好きで好きで、そ一れでナーゴヤに越して来たばかりの老人だでヨ。
だから、これはテレビで覚えたインチキのナーゴヤ弁じゃ。テレビじゃ、ミヤーミャー言う
とったけど、実際にはそうでもないみたいだで。
それはそうと、わしのパチンコ仲間で出る台の番号をパソコンで研究しておるやつがおるで
ョ。わ一しはそのソースリストを持っとるでな、プログラムの無駄をなくそう思って—部直し
てやったでヨ。
L 00 P 1 :
MOV
AX , [ SI ]
- >
L 00 P 1 :
MOV
AX , [ SI ]
CMP
AX .5
CMP
AX ,5
JB
SUBRT
JB
SUBRT
CMP
AX , 30
CMP
AX , 30
CMC
CMC
JNB
SUBRT
JNB
SUBRT
ADD
SI ,2
ADD
SI ,2
L 00 P 2 :
DEC
CX
L 00 P 2 :
LOOP
L 00 P 1
JNE
L 00 P 1
SUBRT :
RET
SUBRT :
RET
以来、出る台がさっぱり当たらなくなったでヨ。わしゃ、なんか悪いことでもしたじゃろか
. ?
パチンコ老人(愛知)
■答^-«
最近はパチンコ屋といっても、半分くらいはスロットマシンが置いてあるよ
うです。やはり、パチンコが一番面白かったのは、左手で1つずつ玉を入れな
がら打つ古き時代じゃなかったでしようか。
8i
あの頃は、神技のような早打ちができる名人がいたり、ひとつぶの玉を右手
で入れては右手ではじくヒマつぶしの老人もいました。それに比べると、現代
はスピードの時代。軍資金も玉もアッという間になくなります。
おっと、こんな話は18禁の方には関係のないことですね。あくまでも、問題
はプログラムの内容に ついて です。
修正したプログラムは、オリジナルより1バイト少なくなっています。もち
ろん、 命令を 実行する過程はまったく同じです。しかし、このプログラムは実
行過程よりも、実行結果に意味があるプログラムなのです。最後のフラグまで
見落と してはなりません 。 LOOP 命令は フラグ 変化を しないのが特徴です。
まず、このプログラムの目的ですが、 SI レジスタで示されるアドレスの中身
を、最大で CX 回(アドレスを+ 2しながら)チヱックし、その結果をフラグで
返すことです。オリジナルのフラグ結果と、修正後の結果を比較してみましょ
う0
[ SI ] を最大 CX 回チェック
オリジナル
修正後
[ SI ] =0〜4
CF =1 ZF =0
CF =1 ZF =0
[ SI ]=5 〜29
CF =0 ZF =0
CF =0 ZF =0
[ SI ]= すべて30以上
CF =1 ZF =1
CF =1 ZF = 不定
CX 回のチエツクの間に [ SI ] 二〇〜29となれば、フラグ結果はどちらも同じで
す。しかし、最後まで [ SI ] が30以上の値であった場合には、修正プログラムで
は ゼロ フラグが不定です。不定といっても、 セロフ ラグが1になるのは直前の
「ADD SI , 2」の演算結果が0となる時だけで、それ以外はすべて ゼロ フラグ
は立ちません。
したがって、せっかく最後まで30以上であっても、 RET 時には途中に〇〜4が
あったと いうフラグ 結果になってしまうわけです。これでは、 このプログラム
の価値も不定になってしまうはずです。
今回は、フラグ変化がないという理由で LOOP 命令が使用できませんでした
82
が、その逆にフラグ変化がないという特徴を利用することもあります。 LOOP 命
令は単にループに便利というだけでなく、このような使い分けをすることも活
用したいポイントなのです。
なお、このサブルーチンをコールしたほうのプログラムでは、結果による条
件分岐の順序を間違えないように気を付けてください。先ほどのフラグ結果表
を見ながら、どの条件で分岐させるべきが確認しておきましょう。それにして
も、なんだか危ないプログラムです。
83
一
34
INC 齢とキヤリ-フラグ 2
/、 口—! I ここはニューヨークです。父の仕事の都合で、半年前にこちらへ家族そろって
引っ越してきました。広大な国アメリカは、なんでもビッグです。アイスクリームもス
テーキも日本の倍はあります。
家では日本語、外では英語、そして夜はマシン語の毎日です。いま、フラグの利用法について
色々研究しています。ところで、 me 命令や DEC 命令がなぜキャリーフラグに対して無変化に
なっているのかがわかりません。演算結果がキャリーフラグに反映されたほうがプログラム
しやすいと思うのですが……。
最近、「+1」や「一1」する演算の後でキャリーフラグを利用するといったケースにしばし
ば出会いますが、こんな時には、仕方なく 「ADD reg , l 」 や 「SUB reg , l 」 で置き換えてプ
ログラムを組んでいます。
現地名•早口卜厶(ニューヨーク)
■答--
アメリカがなぜ広大かといえば、それが現実だからとしか答えようがありま
せんね。同じように、 INC / DEC 命令でキャリーフラグが無変化なのは、それが
現実だからです。なぜそうなったか、それは CPU を設計した本人でなければ正
確にはわかりませんが、きっとそのほうがいいと確信していたからに違いあり
ません。
確かに、キャリーフラグの変化がほしい場合には、この結果には不満がある
かもしれません。 「 ADC 」 や 「 SBB 」 命令などの演算命令もあるし、キャリーフ
ラグを利用したジャンプ命令もあるからです。
しかし、キャリーフラグが無変化ということは、キャリーを壊さずに 「 INC 」
や「 DEC 」 命令が使えるということでもあるのです。無変化を嘆くのではなく、
無変化という現実を利用することが先決でしょう。右の例を見てください。
このプログラムは、 DATAA と DATAB にあるデータを1バイトづつ加算し
て、 DATAA に結果を返すプロシージャですが、もし演算の結果、桁あふれを生
じた場合には、次のデータアドレスを求めた後、処理を中断してリターンしま
す。このように、キャリーフラグが無変化であるがゆえに成立するプログラム
84
DATAA
DB
1,2,3,4,5
DATAB
DB
10,9,0 FFH ,7,6
DTCNT
DW
5
ADDAB
PROC
MOV
AX'CS
MOV
DS.AX
MOV
Dl,OFFSET DATAA
MOV
SI,OFFSET DATAB
MOV
CX,DTCNT
CLC
CLD
ADDLP :
MOV
AL ,[ SI ]
ADD
[ DI],AL
INC
SI
INC
Dl
DEC
CX
JZ
ADRET
JNC
ADDLP
ADRET :
RET
ADDAB
ENDP
もあるのです。実に、先見の明ある合理性ではないですか。この合理性を当然
のごとく活用できるようになると、マシン語でも早口(早プログラミング?)
になれるかもしれませんね。
85
閩
35
麵的な疑似乱数
- ちらは、第99次南極観測越冬隊の親衛隊です。越冬隊員に憧れて、秘かに南極までやっ
w て来ました。昼間はペンギンと戯れ、夜は全員一丸となってパソコンの前に座っていま
す。その目的は、いつ襲ってくるかわからないプリザ ー ドを予測するプログラムを組むことで
す。
しかし、はっきり言ってこれは ゲームみ たいなものです。 というのは 、ブリザードを色々と検
討した結果、ほとんど乱数に近い出現という結論に達したからです。それはそれでいいのです
が、誰もマシン語で乱数を発生させる方法がわかりません。
ブリザードに襲われるのは、まったく乱数というわけでもなく、大きな周期もあるようです。
だから、あまり完全無欠の乱数というのもマズイのです。こんな都合のいい乱数なんてあるで
しょうか。
アツ、ブリザードに襲われて停電になってしまった……。
ペンギン野郎(南極)
| B -- .
南極からの質問……?
どうやら、この質問は モールス 信号で送られてきたようです。そもそも、こ
の モールス 信号というのは、わからない人にはピッピッピの乱数にしか聞こえ
ません。それでも困った時のために、 SOS (トトトツーツーツートトト)だ
けは覚えておくようにと、子供のころよく言われたものです。
例えば、船會に閉じ込められた時とか、秘密基地に誘拐された時とか……。
でも、そんな経験があるはずもなく、いまだに使ったことはありません。
さて、おたずねの乱数ですが、一般的に コンピュータで 乱数と いっているの
は、本物の乱数ではなく疑似乱数が多いのです。これは簡単な計算式によって、
一定の周期でランダムに近い数値が得られるようにしたものをいいます。
なんだニセモノか、などとバカにしてはいけません。ゲームなどには、かえっ
てこのほうが適して いるので す。というのは、本物の舌 L 数には0が何回も連続
するとか、しばらくの間は10以下ばかりとか、本物がゆえに舌し数として好まし
くない現象が起きることがあるからです。
86
その点、疑似舌 L 数はいかにも乱数という感じで バラつ いてくれます。ここに
紹介する乱数は、コールするたびに AL レジスタにラン ダムな数値を入れて返す
という、最も簡単で一般的な乱数ルーチンです0
プログラムの内容は、前回の値を5倍し、さらに1を加えたものを新乱数と
するというものです。最後に加える数値(ここでは 1) は、0以外であれば何
でもかまいません。この舌し数がどのようにループするのかを示しますので、舌し
れ方の特徴を確認してください。
また、最後に1を加えないとどうなるか、あるいは5倍ではなく 2倍とか3
RND 1
PROC
MOV
AL,CS : SEED 1
MOV
AH,AL
ADD
AL,AL
ADD
AL,AL
ADD
AL,AH
INC
AL
MOV
CS : SEED 1 ,AL
RET
RND 1
ENDP
SEED 1
DB
0
F0E0D0C0B0A090807060504030201 000
3333333333333333
69CF258BE147AD03
AAAAAAAAAAAAAAAA
7E5C3A18F6D4B 290
5555555555555555
E94FA50B61C72D83
4444444444444444
9876543210 FEDCBA
7777777777777777
BE147AD 0369 CF 258
EGEEEEEEEEEEEEEE
B2907E5C3A18F6D4
9999999999999999
50B61C72D83E94FA
8888888888888888
76543210 FEDCBA 98
BBBBBBBBBBBBBBBB
47AD 0369 CF258BE1
2222222222222222
4B2907E5C3A18F6D
DDDDDDDDDDDDDDDD
0B61C72D83E94FA5
CCCCCCCCCCCCCCCC
9876543210 FEDCBA
ffffpfffpfffffff
147AD 0369 CF258BE
6666666666666666
07E5C3A18F6D4B29
111111 lx 11 11lx 1i 11 11IX 11IX 111111
0B61C72D83E94FA5
87
倍にして 1 を加えたらどうなるか……。プログラムを少し変更するだけでテス
卜できますから、ぜひ試してみてください。乱数の乱れを改めて認識できるで
しょぅ。
でも、こんなんで本当にブリザードの予測ができるのかどうか、少しばかり
疑問が残ってしまいます。
88
閩
36
相加法による乱数
_ 生のうち、一度でいいから宝くじの一等に当たってみたい。そう思って20年。もう何枚
のハズレくじを買ったことでしょう。当たるのはいつも末等ばかり……。
末等だけは、10枚買えばイヤでも当たります。だから、あれはハズレと一緒です。しかし、こ
こまでハズレが連続したら、当たる時は一等に違いないはず。それが、唯一の心の支えです。
やっぱり私は楽天的でしょうか。
でも、最近は子供も大きくなってきたし、少しはシビアになろうと思い、宝くじの番号を指定
して購入するようにしました。もちろん、いつも思い通りの番号が買えるとは限りません。し
かし、少なくとも運は向上すると思うのです。ただ、今のところ結果は同じでハズレばかりで
す。
そこで、今度は購入番号をパソコンの乱数に選ばせようと思います。乱数で各桁ごとの番号を
決めたいのですが、私の知っている乱数 (5 倍して1を足す)では、すぐループしてしまい面
白味がありません。もう少し変化に富んだ乱数はできないでしょうか。
宝塚九二男(兵庫)
■答-《
宝くじ。本当に当ててみたいものです。よく「運がよければ……」といいま
すが、いったいどの程度の運なのでしょうか。
一等の出る確率を計算すると、宝くじによっても、また一等賞金の額によっ
ても違いますが、だいたい百万分の一とか、二百万分の一といった感じが多い
ようです。いずれにしても、桁が多すぎてピンと来ない数字です。
では、直径1ミリの砂つぶをすき間な〈千メートル並べ、その中の1つぶだ
けが一等になるといったらどうでしょう。 書いてみて、確率の低さに驚い
たのは、ほかならぬ自分でした。
さて、例の5倍して1を足すという乱数(問 35) ですが、コールするたびに
偶数/奇数が入れ替わり、下位4ビットは16回で一巡してしまいます。全体的
にも256回で元の値にもどりますから、利用できるのはせいぜい簡単なゲーム程
度と考えたほうがよさそうです。
そこで、宝くじに応用できるような複雑な乱数の登場です。といっても、あ
89
まり計算時間がかからない、相加法というものです。
この基本的な考え方は適当な数値 SEED 1、 SEED 2 を用意して、 コールす るた
びに SEED 1 二 SEED 2、 SEED 2 二 SEED 1 + SEED 2 を単純に繰り返すものです。
計算は16ビットで行い、その上位8ビットを乱数に取るので、その値からは
次回の乱数を予測できなくなります。
RND2
PROC
MOV
AX,CS : SEED 1
MOV
BX,CS : SEED2
ADD
AX,BX
MOV
CS : SEEDl.BX
ADD
AX,3711H
MOV
CS : SEED2,AX
XCHG
RET
AL,AH
RND2
ENDP
SEED1
DW
9371 H
SEED2
DW
5713H
最後に加える371 1 H は特に意味のない数値であり、舌し数にさらに乱れを生じ
させるためのものです。この数値は、他の初期値とは異なり、0であってもか
まいません。また、色々な値を入れてテストしてみてください。
もし、当たりそうな乱数が得られるようだったら、ぜひ教えてもらいたいも
のです。これは本気です……。
9〇
閩
37
乱数利用の翻
いでませ一、山口へ。山口といえば長州。長州といえば、維新の嵐。革命戦士の心意気
^でマシン語を制覇するゾ!!
……と意気込んでみたけど、いま挫折しかかっています。ぼくはプロレスラーと精神構造が一
体化している高1です。小さい時からバーベルで鍛えてきただけあって、自慢の胸囲は 110 cm
を誇ります。
挫折の原因は単純です。なにかにつけて乱数乱数といいますが、ぼくには乱数の意味はわかっ
ても、それをどう利用するかがわからないのです。例えば、ゲームなどでは敵の動きを乱数で
決めることがあるそうですが、動きは8方向程度なのに、乱数では〇〜255までの数ができてし
まいます。
例えば、1〜8の舌し数がほしければ、その数が出るまで乱数ルーチンをコールしろということで
しようか 0
CRNDl : CALL
RNDl
CMP
AL ,8
JNB
CRNDl
INC
AL
— fRNDlJ は問35の乱数ルーチン
― AL =1 〜8の乱数
あるいは、もっと特殊な乱数ルーチンがあるのですか。どうか、この挫折から立ち直れるよう、
カツを入れてください。
男一匹長州軍団(山口)
■答一
喝(かつ)!!
これで、挫折から立ち直れるなら何度でもカツを入れてあげましょう。喝!!
なに、まだ挫折から立ち直れない 。喝!!
エーッ、まだ……。よく考えたら、こんなことをするより、先へ進んだほう
が早く立ち直れそうですね。では、舌し数の利用法へと進むことにしましょう。
舌し数は、作るよりどう利用するかでその価値が決まります。料理の味がコッ
クさんの腕前で変わるように、舌し数もうまく活用することが大切なのです。ど
んなにいい舌し数ルーチンでも、利用方法が悪ければ結果的に悪い乱数になって
91
しまいます。
例えば、5倍して1を足すという簡単な乱数(問 35) を用い、確率1/2の割合
で条件分岐させるとします。
A
CALL RND 1
巳
CALL RND 1
ROR AL ,1
ROL AL ,1
JB PROG 1
JB PR 0 G 1
PROGO : !
PROGO : |
A も B もプログラム的には似たようなものです。しかし、得られる結果は
まったく違います。 A のほうは、キチンと1回おきに分かれてしまい、舌し数を
取った意味がなくなっています。一方、 B のほうはある程度予測不可能な分岐
をしてくれます。
もちろん、どちらも256回実行すれば分岐割合は同じですが、舌し数ルーチン
は何もこのプログラムだけで利用されているとは限りません。下手をすると A
のプログラムは同じ場所へのジャンプしかしなくなる可能性だってあるわけで
す。
したがって、簡単な乱数を利用する時には、その舌し数の性格も頭に入れて利
用することが大切です。 「 RND 2」 (問 36) を利用すればそういう心配は不要です
が、 「 RND 1」 には 「 RND 2」 よりプログラムが短い上、速度も速いという特徴
があるのです。一概に役に立たないというのではなく、場合による使い分けを
したいものです。
では、質問にあるような数値を乱数で作ってみましょう。乱数ルーチンは
「 RND 2」 を使用するものとします。これは、 「 RND 1」 では下位4ビットが16
回で ループして しまい、今回の応用には適さないからです。
(1) 乱数から〇〜7の数を作る (2) 乱数で1〜8の数を作る
CALL
RND 2
AND
AL , 000001 11 B
INC
AL
CALL
RND 2
AND
AL ,00000111 B
92
要するに、乱数ルーチンで得た数値をそのままの姿で利用するか、それとも
加工して好みの数値にするか、それを決めるのは「あなた」というわけです。
知ってしまえば簡単なものですね。
挫折から復活の呪文へ……喝(かつ)!!
93
琶
38
乱数の応用
^たくし生まれも育ちも葛飾柴又です。帝釈天で生湯をつかり、姓は車、名は寅三郎。人
つ/呼んで『フーセンの寅』と発します。以後よろしうおたの申します。
わたくしの職業は、全国 津々浦々に 出向き、立地条件のよい 場所を 見つけては風船の 直営店を
開くことであります。そのためには、全国の祭り、縁日、運動会。バザーにイベント、歩行者
天国。あらゆる催し物の場所と日時を、正確に記憶しておくことが大切なのでございます。
カバンひとつで長期の出張、つらいけれども気楽な身です。唯一の不安は、行き先を間違えて
商売をし損なうことです。しかし、いまでは一枚のフロッピィディスクがあるので安心です。
そこには、柴又のオイちゃんの家でインプットした、全国の催し物の情報が入っております。
こう見えても、プログラムは自前、それもマシン語です。
お祭り好きな日本では、いつもどこかで祭りが開かれています。客足の予想なども、そのプロ
グラムで知ることができます。しかし、欠点はいつも同じ結果しか表示してくれないことで
す。
そこで、乱数を利用して上下に変化をつけたいと思うのですが、乱数をどのように活用したら
いいものか、悩んでおります。どうかよろしくご教授くださいませ。
ちなみに、プログラムはデパートで実行させております。
旅先にて……風船のトラ(福井)
■答-^
地方を巡業中のフーセンの寅さんも、コンピュータで行動を管理していたの
ですか。気ままな商売に見えても、結構苦労していたんですねェ。
どのようなプログラムで客足の予想までしているのか、これだけではわから
ないのが残念ですが、とりあえず、+/—を含んだ舌し数値を得るのが目的のよう
です。もっとも、問2にあるように、 +/- というのは使う側の勝手ですから、
何もしなくてもすでに一128〜+ 127の数値として扱うことはできるわけです。
しかし、これでは上下の幅が広すぎますね。計算をしたとたんに8ビットの
限界を超えて、足したつもりが少なくなってしまう恐れもあります。
[例]
150 (元の数値)+120 (変動幅)=14 —8 ビットの限界を超えたため
94
なかには、客足の予想をするのに、8ビットではそもそも無理があると感じ
る人もいるでしょう。しかし、数値には単位というものがあります。例えば、
100という値でも後ろに「00」を付ければ10000を表現したことになるように、
単位次第でいくらでも表現できる幅はふくらむのです。
ゲームの スコアな ど、 内部では1点単位、画面では飾りの「00」を付けて100
点。そんな見え見えのゴマカシもあるほどです。ということで、 「 RND 2」 (問 36)
を利用して、上下幅のある数値を作ってみます。
(1) 一7〜+7の数を作る
— 「AND 100001 11BJ としただけでは
一7〜+7とはならないことに注意
⑵30%の確率で雨が降る。雨ならば一7〜一4の数値を、雨でなければ+4〜+7の数値を作
る。(256/100 = 1%と考える)
—「ADD AL.4J でもよい
—BL=4 〜7の乱数
—30%の確率 (77=30X256/100)
これらの例のように AND 命令がいつもうまく使えるとは限りませんが、加
減算をして調整したり、確率による条件分岐を組み合わせることで、たいてい
は条件に見合った舌し数値を作り出すことができます。
どうやっても条件からはみ出してしまう数値が出る場合は、条件に見合うま
CALL
RND 2
AND
AL ,00000011 B
OR
AL ,00000100 B
MOV
BL,AL
CALL
RND 2
CMP
AL ,77
MOV
AL.BL
JNB
NRAIN
NEG
AL
NRAIN : !
CALL
RND 2
AND
AL ,00001111 B
ROR
ALJ
JNB
NONEG
NEG
AL
NONEG :
?
95
で同じ処理を繰り返すか、確率の狂いは無視して適当な数値に決めてしまうこ
とです。いい加減で いいのが 乱数なのです。
タコはイボイボ、ニワトリゃはだし。イモムシゃ19で嫁に行く。舌 L 数いろい
ろ、よく見りや数字。足して引いてりゃ丸くなる……。
96
3
39
乱数に変化をつける
L たしは女の子ですが、パソコンが大好きです。とくに、面白いゲームがどういうふうに
Aj プログラムされているかを考えると、胸がワクワクします。
ゲームと しては、 アクション ゲームよりか、ドラ クエ みたいな RPG が大好きで、わたしもい
つの日かあんなゲームを作ってみたいナと思います。だから、少しは マシン 語も勉強しまし
た。
敵とか出すのって、乱数を使うんでしよ。それくらいは知っています。でも、ゲームでいう乱
数は疑似乱数のはずです。だから、ゲームをスタートして同じように動けば、誰がやっても同
じ敵が同じ場所に出てくるはずだと思います。
ところが、ためしにそういう実験を友人とやってみると、ソックリ同じにはなりませんでし
た。もしかすると、本物の舌し数ですか……?
中3あきな(石川)
■答- •
女の子のパソコンファンが 近ごろ増えてきているらしいですね。これで、 パ
ソコンの 未来も明るくなりそうです。
パソコンの 魅力の1つに、市販ソフトとまったく同じものを本体で作ること
ができるという特徴があります。これは、プログラムを組まない人にとっては
無用の長物です。その点、遊ぶ面白さから作る面白さに気が付いた石川のあき
なちゃんはエライっ!!
未知のものを作る時のスリル、そしてプログラムを初めて実行する時の不安
感。これはもう体感 RPG そのものです。プラモデルだって、完成してからより、
作っている時のほうが楽しいし夢があります。
TV ゲームで 遊んでいる子供たちが、そういった パソコンの 特徴に気が付い
た時、 パソコンは 飛躍的に広がるでしよう0
さて、舌し数としては、問36にあった相加法のほかに、コンピュータでは乗算
命令を使った乗算合同法に基づく舌し数がよく用いられます。これは、単純に前
の乱数に259をかけていくものです。なお、この259は、有効ビット数と複雑な
乗算合同法の理論により求められるものです。単純に数値をかけるだけですか
97
ら、プログラムとしては次のように簡単なものです。
- SEED1X259
しかし、どんな方法を使うにしても、初期値が同じでプログラムを呼ぶ回数
が同じであれば、全く同じ乱数が発生してしまいます。そこで、この乱数の初
期値を変えて異なる乱数体系にすれば、ゲームにも変化が生じることになりま
す。
では、どのようにして乱数の初期値を変えたらいいでしょうか。乱数の初期
値に乱数を使うというのでは「卵が先かニワトリが先か」になってしまいます。
悩みそうな問題ですが、いくつかの簡単な解決法があります。
(1) 名前の合計(文字もマシン語上では数値です)を乱数の初期値にする。
これは RPG などではよくやりますが、名前が同じだと合計も同じになっ
てしまいます。しかし、それも名前による 一種のゲーム 性です。 このプロ
グラムでは、文字コードをアスキーコードで表現し、0を名前のエンドサ
インにしています。
RND 3
PROC
MOV
AX,CS : SEED 1
MOV
BX,AX
SH し
BX.l
ADD
BX,AX
MOV
AH,AL
MOV
AL ,0
ADD
AX # BX
MOV
CS : SEED 1 ,AX
RET
RND 3
ENDP
SEED 1
DW
3471 H
NAMAE
DB
’アキナ ’,0
START :
MOV
BX,OFFSET NAMAE
MOV
DX ,0
STAT 1:
MOV
al ,[ bx ]
OR
AL.AL
98
JZ STAT 3
ADD AL,DL
JNB STAT 2
INC DH
STAT 2 : MOV DL,AL
INC BX
JMP STAT 1
STAT 3 : MOV SEED 1 ,DX
(注) DS = CS と仮定する
(2) キー入力のループの 中で、舌し数 ルーチンをコールす る。
一般に、どんな ゲームで も最初にタイトルなどがあり、なにかキーが押さ
れるのを待つようになっています。そのキー入カチェックのループで、乱
数ルーチンをコール すれば、 ゲーム 開始時には乱数にズレが生じていると
いうわけです。
(3) コンピュータのタイマーの秒の値を乱数の初期値とする。
コンピュータ本体には、日付や時計機能が備えられているのが普通です。
その中で変化が顕著に現れる秒を初期値に利用するものです。
あきなちゃんだけでなく、せいこちゃん、きようこちゃん、のりこちゃん。
それに、さゆりちゃん、わかこちゃん……。みんな パソコンフアンに なればい
いのに . ネ。
99
閩
40
BP レジスタとは
なたは神を信じますか?
の わたしは神を信じます。わたしは ニューギニアに いるドイツ人の牧師です。わたしは神
の教えを広め、人々の幸せと平和を祈り、貧しい者、富める者、病める者、健康な者、 すべて
の人々の心の悩みを救うため、 ここニューギニアへやって来ま した。
ところで、わたしの友人に変な日本人がいます。彼は、わたしに悩みを解決してくれと言いま
す。ところが、その悩みとはなんと マシン 語に ついて です。これには、わたしも困ってしまい
ます。
彼の話によると、ある日 BP レジスタの存在を知り、いろいろと研究したそうです。その結果、
働きとしてはセグメントベースに SS レジスタを使う以外は BX レジスタとほとんど同じよ
うな働きをすることがわかったそうです。これは便利と最初のうちは (DS :) でセグメント
ベースを変更して使っていたそうですが、ふと BP レジスタの存在価値とは何なのだろうと、
考えるようになったそうです。
彼は、そのことで悩み、わたしに相談してきました。わたしは人の悩みを解決するのが仕事で
す。わたしはこの手紙を英語で書き、それを彼に日本語に訳してもらいました。
だから、この手紙はわたしの手紙であっても、書いたのは彼であり、悩んで いるのは わたしで
あっても、悩みは彼のものであり……。なんで、わたしが悩むのか、それがまた悩みとなって
……ナニがどうなっているのか、わからなくなりました。
オー、神よ。悩めるわたしを救いたまえ。アーメン……。
悩める牧師(ニューギニア)
■答 — *
「あなたは神を信じますか?」
「信じます。ただし、困ったときだけ」
……というのが、多くの日本人だそうです。無理もないですネ。生まれた時
は神社にお宮参り、結婚式は教会で、お葬式はお寺で、そして普段は祈らない
……。これが通用するのが日本ですから。
そんないい加減な信者の一人ですが、いつものお礼に悩める牧師さんを救っ
てあげたいと思います。
まず、 BP レジスタを考える前に、ある プロシージャ に対して パラメータを渡
す方法を考えてみましょう。
100
1 ……レジスタを使う方法
2 . メモリ変数を使う方法
3……プログラム.コードへ含ませる方法
4 スタックを利用する方法
以上4つの方法が考えられますが、この最後のスタックを用いる方法はしば
しばコンパイラなどで用いられているようです。この利点は変数としてのメモ
リがスタック上にあるために、プロシージャがコールされた時だけ変数が存在
する、すなわち、リターンした場合、変数エリアが解放されるため、余計なメ
モリを消費しないですむのです。そして、このスタック上の変数の参照を前提
として生まれたのが、、この BP レジスタだったというわけです。
さらに、プロシージャ独自の変数(ローカル変数)を一時的にスタック上に
とった場合にも非常に便利な存在となっています。
ですから、1、2、3の方法のみでパラメータ渡しをしていれば、まったく
といっていいくらい BP レジスタの存在意義は感じられないでしょう。
では、ここで、パラメータ1つをスタック渡しで、また、初期値、5、13の
ローカル変数と8バイトのローカルな変数域を持つ TEST 1という NEAR 夕
イプのプロシージャを作ってみましよう。
— SP を BP レジスタへ
— 初期値5のローカル変数を確保
-> 初期値13のローカル変数を確保
-初期値不定の口ーカルな変数域を8バイト確保
— 親からのパラメータ1の参照例
— 初期値5の変数の参照例
— 初期値13の変数の参照例
-> 8バイト確保したローカル変数域の使用例
TEST 1 PROC
MOV
MOV
PUSH
MOV
PUSH
SUB
MOV
MOV
MOV
MOV
NEAR
BP ; SP
AX ,5
AX
AX ,13
AX
SP ,8
CX,[BP + 2]
AX ,[ BP -2]
BX ,[ BP -4]
[ BP -6 ],BX
101
MOV
RET
TEST 1 ENDP
SP,BP
— >
スタックを元に戻す
まず、プログラムの先頭で、 BP レジスタへ現在の SP レジスタ値を格納しま
す。次に、各ローカル変数の初期値を AX レジスタを介してスタックへ格納し
ます。さらに、 SP レジスタから8を引いて、ローカルな変数域8バイトを確保
します。
これで、ローカル変数の確保がすべて終わりましたから、 SP レジスタは
CALL 命令等で間接的に操作はされますが、直接操作することは最後まであり
ません。
ここで BP レジスタの登場となるのです。 BP レジスタによるメモリの参照
は、 SP レジスタと同様に、 SS レジスタをセグメントとして暗黙に指定してい
ます。しかしながら 、 BP は SP とは異なり、 CALL 命令や割り込み命令等の影
響は受けないのです。したがって、安心して変数の参照に使えることになるの
です 。
さて、プログラムの先頭では BP に SP を格納していますが、これは SP レジ
スタを元に戻す時に使えるばかりではなく、 「 BP +*」 であれば親からのパラ
メータである こ とがわかるし、 「 BP -*」 であれば ローカル 変数である こ とがわ
かるなど、プラスひ的な効果と利点があるのです。
なお、 [ BP +0] にはプロシージャ本体の戻り番地が格納されていますからく
れぐれも破壊しないようにしてください。また、 FAR タイプではセグメントア
ドレスもスタックにキープされていますから注意が必要です。
親から パラメータを 渡す場合には、次のように、あらかじめ パラメータをス
タツクへ格納してから呼び出すことになります。
MOV
AX,PARA 1
PUSH
AX
CALL
TEST 1
POP
BX
102
プログラムが 終了し 、 「POP * * * *」を 実行 すれば、「* * * *」 へ PARA 1
がプロシージャ TEST 1 で 加工された内容を取得す る ことができます(ここでは
BX レジスタとしている)。
BP レジスタには、このようにとても大切な役割があるのです。とはいえ、沉
用レジスタとして用いたり、質問のように DS : と共に他のメモリ参照にも使え
るなど、かなり色々な役割を持たすことができます。ようするに、難し〈考え
ずに自由に使えばよいのです。
これで、悩める牧師さんを救えたとしたら、わたしは神となるのでしょうか。
オヤ、本当の神の声が聞こえてきました。
あなたは神ではなく紙。つまり本です、アーメン……〇
1〇3
_
渡しプログラム.コ-ド編
rj シは悪魔神官バーボン . 。
ノつまり、酒の好きなおまえたち人間の酔った時の心を司る神じゃ。酒は人の心を気持ち
よく狂わせ、理性を失わせる。酒は百薬の長、祝い酒、おとそ、おみき……、飲む理由はいく
らでもある。
そこがワシのつけ目じゃ。やがて、ジキルとハイドのように、まったく違った人間ができ上が
る。それが、おまえたちの裏の心だ。わかるか、心に表も裏もない。裏が表になれば、それが
表になるのだ。その時こそ、世界がワシのものになる。
……というのが、ワシが描く理想の世界なのだが、どうも理想と現実は違うような気がする。
いつまでたっても、理想の世界にならんのじ ゃ。
そこで、ワシは人の心をコンピュータで分析しようと思う。うまい具合いにプロシージャへの
パラメータ渡しの方法が問40にあったのでさっそく利用することにしたのだが、第3番目の
プログラム • コードへ含ませる方法というのがわからん、そこで具体例と共に解説してほし
い、というのが質問じゃ。分析が終わったからといって、ワシの理想通りになるとは限らんか
ら、安心して質問に答えてくれ。
天オバーボン(酒乱界)
■答 -一
これは、恐ろしい質問です。私が酒飲みなら、不安でとても答えられないの
ですが、幸か不幸かわたしは酒が飲めません。だから、平気で質問に答えるこ
とができます。
プログラム•コードへパラメータを含ませるとは、次のようにプログラム中
にデータを含ませてしまう方法などのことです。
CALL TEST 1
DB ^ BCDEFGS '
LABEL 1 :
このように、 CALL 文の 直後、コー ド中にパラメータを 置く ことによって、
容易に パラメータ 位置を取得するこ とがで きます。
1〇4
呼び出されたプロシージャ TEST 1 で注意しなければならないのは、戻り先ア
ドレスがパラメータの先頭アドレスを指しているため、リターンする場合には、
この戻り先アドレスを正しい戻り先に更新してから、リターンしなければなら
ないということです。次に例を示しますから参考にしてください。
TEST 1
PROC
MOV
BP.SP
MOV
BX ,[ BP ]
TESL 1 :
MOV
AL , CS :[ BX ]
CMP
AL ,,$’
JE
TSEND
CALL
PRINT
INC
BX
JMP
TESL 1
TSEND :
INC
BX
MOV
[ BP],BX
RET
TEST 1
ENDP
—1 文字表示ルーチン
ところで、酒を飲むと頭がさえるという人間もいることを、お忘れなく
悪魔神官バーボン殿。
1〇5
I
42
ブロック充塡
^ 渡へ一佐渡へ一と、草木もなびィーく〜 . 。
と、歌われたのも今は昔のお話です。最近では、佐渡で金が取れたことさえ知らない人
がいます。しかし、私はまだまだ佐渡で金は出ると信じています。だからこそ、全財産を処分
してここへやって来たのです。
私は、自称地質学者。他称『ヘンなおじさん』です。マ、多少は他称のほうが当たっているか
もしれませんが、そんなことはどうでもいいことです。現在、コンピュータにより地層を分析
し、夢にまで見た金脈を探しています。
もっとも、コンピュータといっても中古のパソコンです。独学で覚えたマシン語を使っていま
すが、実行速度が遅く、なかなか分析は進みません。ここにあるのはメモリを一定のデータ(こ
こでは〇)で埋めるルーチンです。
XOR
AX , AX
MOV
BX , xxxx
MOV
CX ,120
FLOOP : MOV
[ BX],AX
ADD
BX ,2
し0 OP
FLOOP
RET
何度も使われるので速ければ速いほどいいのです。もし、うまく改善してくれたら、金が出た
時に1 kg ほどあげましょう。
名物•金脈おじさん(佐渡島)
■答-《
1 kg の金 ということは、時価に換算すると ウ〜ン。いずれにしても
大金であることは間違いありません。なんとしても、この質問にだけは答えな
ければ……。
まず、質問にあるプログラムが何クロックかかっているか、それを計算して
みます。その後でどの程度のスピードアップが計れたか、改善したプログラム
と実際に比較してみましょう。
ここで注意が必要なのは、メモリに対するアクセスの場合、そのメモリが偶
1〇6
数番地であるか奇数番地であるかによってクロック数が異なるということで
す。奇数番地に対するメモリ•アクセスでは、16ビット•オペランドの場合4
クロック多く時間を消費します。まず、先ほどのサンプルプログラムを偶数と
奇数とに場合分けをして、消費クロック数を求めてみましょう。
XXXX が偶数の場合
3
X
1
=
3 ….き
. XOR
AX , AX
4
X
1
二
4 •.…
. MOV
BX,xxxx
4
X
1
=
4…
• MOV
CX .120
10
X
120
1200…
■ MOV
[ BX],AX
4
X
120
=
480 …"
.ADD
BX ,2
17
X
119
=
2023…
.LOOP
FLOOP (ループ時)
5
X
1
=
5…
■ LOOP
FLOOP (通過時)
TOTAL :
3719 クロ
ック
XXXX が奇数の場合
3
X
1
=
3…
. XOR
AX , AX
4
X
1
二
4 ……
_ MOV
BX.xxxx
4
X
1
=
4 ……
, MOV
CX ,120
14
X
120
=
1680 ……
■ MOV
[ BX],AX
4
X
120
二
480 ……
• ADD
BX ,2
17
X
119
=
2023 ……
LOOP
FLOOP (ループ時)
5
X
1
=
5……
_ LOOP
FLOOP (通過時)
TOTAL : 4199クロック
改善案一①: XXXX が偶数の場合
MOV
BX,xxxx
4
XCHG
BX,DI
2
MOV
AX,DS
2
MOV
ES,AX
2
XOR
AX , AX
3
MOV
CXJ 20
4
CLD
2
REP
STOSW
2 + 9 + 10X120=1211
XCHG
BX,DI
2
TOTAL :1232クロック
1〇7
改善案一②: XXXX が奇数の場合
MOV
BX # xxxx
4
XCHG
BX,DI
2
MOV
AX,DS
2
MOV
ES ; AX
2
XOR
AX , AX
3
MOV
[ DI],AL
10
INC
Dl
2
MOV
CXJ 19
4
CLD
2
REP
STOSW
2+9+10 X 119=1202
MOV
[ D 1 ],AL
10
INC
Dl
2
XCHG
BX'DI
2
TOTAL :1246クロック
2バイトずつメモリを埋めていたのを、転送命令に置き換えただけですが、
実行速度は約 7 割ほどアップしています。速度を追求する場合、この例では、
データが16ビット単位ですから、メモリが偶数か奇数かによって場合分けをし
たプログラムを組まなければなりません。そこで、メモリ•ブロックの先頭ア
ドレスを常に偶数番地に取るようにすると、このようなわずらしいことは考え
なくても済むようになります。
これで、金1 kg が私のものに なるわけないでしようね。
1〇8
閩
43
デ■夕転送
i が輩は、あの有名な「ねずみ小僧次郎吉」の子孫にあたる者だ。もっとも、おまえらだっ
^てその子孫の一人かもしれないがな。なにしろ、ご先祖様の子孫は全国にネズミ算式に
増えているから、今では誰が子孫かわからなくなってしまったのだ。
だが、わが輩こそ本家本元家元元祖、ただ一人‘ねずみ小僧’を名乗れる資格のある子孫なのだ。
なぜかって?映画で見たご先祖様のご尊顔とソックリだからだ。どうだ、まいっただろう。
ご先祖様は、お金をアルところからナイところへ移動していたが、わが輩が移動するのはお金
ではない。メモリにあるデータを、アルところからナイところへ移動しようというのだ。わが
輩のプログラムを見てくれ。
MOV
CX ,10
MOVEL : MOV
AX ,[ BX ]
MOV
[叫 , AX
ADD
BX ,2
ADD
Dl ,2
LOOP
MOVEL
ご先祖様は、日本一のスピードでお金を移動した。わが輩のプログラムは、その子孫として恥
ずかしくないものかどうか、コソッと教えてもらいたい。
根津見狐造(住所不定)
■答- •
ねずみはネズミ算式に増えるといいますが、昔も今もねずみの数はあまり変
わらないような気がします。もし、大昔から計算通りに増えていたら、今ごろ
は世界中がねずみだらけになっていたはずですが、いったいどうなってしまっ
たのでしょう。実に不思議なネズミ算の実体です。
さて、このプログラムではちょっとばかりご先祖様には恥ずかしいようです。
ループ命令まで入れると、1ワード転送するのに45クロックもかかっている
上、プログラムには速度を追求した形跡がまったくありません。せめて、次の
ようにするべきです。
1〇9
XCHG
SI,BX
CLD
MOV
AX,DS
MOV
ES,AX
MOV
cx,io
REP
MOVSW
XCHG
SI,BX
こうすれば、多少準備に手間がかかりますが、実質1ワードにつき17クロッ
クです。トータルで実行時間は半分以下になっています。もし、メモリが両者
共に奇数番地である場合は、次のようにするといいでしょう。
XCHG
SI,BX
CLD
MOV
AX,DS
MOV
ES,AX
MOV
CX ,9
MOVSB
REP
MOVSW
MOVSB
XCHG
SI,BX
なお、 MOVSW や MOVSB 命令を REP と組み合わせないで用いた場合、
CX レジスタは変化しないということにも注意してください。
では、ご先祖様に負けないよう頑張ってください。
110
閩
44
データ局酿送
i たしは女の子よ。でも、ちょっと普通の子じやないの。あまり大きな声じや言えないけ
為ノど、ド•口 •ポ.ウなの。ア、誤解しないでね。悪人じやないんだから。
わたしのこと、世間では「怪盗ルビィの指輪」って呼んでいるみたいだけど、普通の人は知ら
ないと思うわ。だって、それは泥棒さんたちの呼び名ですもん。
わたしのお仕事は、泥棒から盗まれたモノを盗り返して持ち主にこっそり返すこと。だから、
泥棒さんたちから見れば、わたしが泥棒になるの。もちろん、相手が相手だけにお仕事は楽
じやないわよ。なにしろ相手もプロだから手も足も結構すばやいの。だから、それに負けたら
オシマイね。
一番必要なのが頭のすばやさ。パソコンでプログラムを組むときも、高速化は常に考えている
わ。もちろん、各メモリブロックの先頭アドレスは偶数番地にしてあるし、データの移動にス
トリング命令を利用して書くのなんか当然よね。
でも、あの命令ってどちらにしても一方通行でしょ。つまり、 SI が+なら DI も+、 SI が一な
ら DI も 一。 わたしがしたいのは、 SI が十で DI が一という転送なの。ここにあるのじや平凡よ
ね。
MOV
SI,OFFSET
DATA 1
MOV
DI,OFFSET
RUBII
MOV
CX ,10
XLOOP : OLD
LODSW
STD
STOSW
LOOP
RET
XLOOP
やっぱりこれしかないかしら。でも、こんなんじゃ泥棒さんのレベルと一緒よね。きっと、な
にかいい方法がありそうな気がするんだけど……。教えて!!
怪盗ルビィの指輪ちゃん(広島)
■音--
なんか、こうフラフラッと教えたくなるようなお手紙です。きっと、相手の
泥棒もすばやさを忘れて、ついボーッとしている間に盗り返されてしまうんで
は……〇
III
しかし、プログラムにまで高速性を追求しているとは、まさに本物のプロと
いった感じです。でも、本当に女の子なんでしょうか。もしかすると、これも
敵を欺くための手段かもしれません。
さて、このプログラムを高速化するには、ちょっと頭をヒネらなければいけ
ません。というのは、常識的に考えればこれ以外にプログラムを組む方法がな
いからです。というわけで、頭をヒネった結果が次のようなプログラムです。
CLI
MOV
CS : KEEPSS,SS
MOV
CS : KEEPSP,SP
MOV
AX,DS
MOV
SS.AX
MOV
SP,OFFSET DATA1
MOV
Dl , OFFSET RUBII
MOV
CX,10
STD
XLOOP :
POP
AX
STOSW
LOOP
XLOOP
MOV
SS,CS:KEEPSS
MOV
SP,CS : KEEPSP
STI
RET
KEEPSS
DW
0
KEEPSP
DW
0
プログラムの 特徴としては、 POP 命令でデータを1ワードずつ読み出し てい
ることです。そのため、 LOOP 命令を別にして1ワードを転送するのに19ク
ロックで済んでいます。質問にあった方法では、27クロックかかります。
つまり、約3割のスピードアップが実現したわけです。一方、この間は SP を
転送するデータアドレスとして使用していますから、当然のことながらレジス
夕を退避したりサブルーチンをコールしたりすることはできません。もちろん、
割り込みも禁止しておかなければなりません。
112
言ってみれば、これが高速化の代償というわけですが、データが多くなれば
なるほどこの効果は絶大なものとなるでしよう。また、この転送部分をループ
を使わずに連記すれば、ループによる無駄が省けさらに高速になります。
せっかくの高速化テクニックですが、こうして本になると泥棒さんにも見ら
れてしまうのでは . ?
閩
45
3 バイトの加鼸
y ンソーレ。ぼくはバソコンが趣味の剣道部員です。得意技は、正眼からの銳いメンです。
’ かけ声は、もちろん「ソーレ!!」です。
ところで、16ビットのレジスタでは〇〜65535 (0 〜 FFFF h ) までしか計算できません。いまど
き、子供の貯金だってそれ以上です。ただし、ぼくの場合はパソコンを買ったばかりなので、
それ以下ですけど……。
でも、ロールプレイングゲームなんかをすると、経験値やゴールドはどんどん上がっていきま
す。もちろん、どこかに上限はあるでしょうけど、ぼくにはどうやっているのかわかりません。
もしかすると、秘密のレジスタでもあるのでしょうか。教えてくれたら、お礼に元気が出る‘ハ
ブのエキス’を差し上げましょう。
青い珊瑚礁(沖縄)
■答^--
青い海、澄んだ空、まぶしく輝く太陽。そんな沖縄で見た「ハブとマングー
スの決闘」は忘れられません。あの時、一匹目のマングースは無残にもハブの
毒牙にやられてしまったのです。勝っても負けても、勝負は一瞬で終わりでし
た . 。
さて、問題の16ビット以上の計算方法についてですが、もちろん秘密のレジ
スタなどあるわけがありません。レジスタがダメなら、頼れるのはメモリだけ
です。メモリなら何バイト使おうと自由ですからね。例えば、メモリを3バイ
卜使えば、表現できる限界は一挙に〇〜16777215と大幅アップします。
ただし、当然のことながら3バイトを一挙に加減算できる命令などありませ
ん。したがって、すべてプログラムで用意することになります。では、3バイ
卜使用した数値どうしの加算と減算のプログラムを組んでみましょう。それぞ
れの数値はアドレスの若いほうを上位桁とし、計算結果はメモリ ( KEKKA か
らの3バイト)に入ります。
どちらのブログラムにおいても、重要なキーポイントになっているのはキャ
リーフラグです。また、 INC / DEC 命令、 LODS / STOS 命令、 LOOP 命令では
H4
キャリーフラダが変化しないという特徴が、このプログラムを成立させていま
す0
DATA O + DATA 1 DATA O — DATA 1
DATAO DB 1 FH ,20 H ,5 AH
DATA 0 DB 1 FH ,20 H ,5 AH
DATA 1 DB 13 H ,50 H ,88 H
DATA 1 DB 13 H ,50 H ,88 H
KEKKA DB 0,0,0
KEKKA DB 0,0,0
ADD 01 PROC
SUB 01 PROC
MOV SI,OFFSET DATAO + 2
MOV SI , OFFSET DATAO + 2
MOV BX , OFFSET DATA 1 + 2
MOV BX,OFFSET DATA 1 + 2
MOV Dl,OFFSET KEKKA + 2
MOV Dl,OFFSET KEKKA + 2
CLC
CLC
MOV CX ,3
MOV CX ,3
STD
STD
ADDLP : LODSB
SUBLP : LODSB
ADC AL ,[ BX ]
SBB AL ,[ BX ]
STOSB
STOSB
DEC BX
DEC BX
LOOP ADDLP
LOOP SUBLP
RET
RET
ADD 01 ENDP
SUB 01 ENDP
( 注 ) DS = ES = CS と仮定する
これらのプログラムを実用化する場合、 BX / SI レジスタを引数としたサブ
ルーチンとすれば、各種の3バイトデータを計算させることができます。
桁数はメモリの許す限り ( CX レジスタのカウントできる範囲ですが)増やす
ことが可能です。もっとも、それを利用する人間が何桁もの十六進数を数値と
して理解できるかどうかは別問題ですが……。
115
||
46
ストリング鈴の 12 クメント•才一八ーラ仆
らわは卑弥呼……。その昔、わらわはこの耶馬台国を治めておったのじやが、いまだに
イジわらわが治めた場所がわからぬというではないか。
北九州とか佐賀とか大和地方とか、説は色々と出ているようだが、実はわらわも古いことなの
でよく覚えていないのじ や。 というより、わらわの記憶にはインプットされなかったのじ や。
おっと、わらわは本物の卑弥呼でもなければ、その生まれ変わりでもない。実を申せば、わら
わは様々な資料を基に作られたコンピュータ卑弥呼にあるぞ。スイッチポンでわらわは見事
に蘇り、そなたに話しかけるのじ や。
わらわを作ったのは、八丸蜂六(はちまるはちろく)というヒマ人じ や。 わらわが彼と話した
ところによると、耶馬台国の距離と方角と面積のデータは入れてあるのだそうじや。
あとは、データのブロック比較や、ブロックサーチ、ブロック転送などのストリング命令など
を駆使して、秘密を解きあかさねばならぬそうじやが、データが細切れで、しかも色々なセグ
メントに格納されておるとか……。
なんでも、ストリング命令のセグメント•オーバーライドの方法があればいいらしいのじや
が、わらわを作った時のアセンブラには許されていないというのじや。当然のことながら、わ
らわに分かるわけがないではないか。そこで相談じやが、ストリング命令のセグメント•オー
バーライドの方法を教えてほしいのじや。
もしも、この耶馬台国の秘、密が解き明かせて、わらわが人間に生まれ変わったなら、そなたの
嫁になってやってもよいぞよ。
卑弥呼の部屋(奈良)
■答- -
嫁……だなんて、あまりに恐れ多くて、丁重にご辞退申し上げます。凡人に
は凡人の歩む道があり、ストリング命令のセグメント •オーバーライド ごとき
で 嫁に来られた のでは 身体が いくつ あっても足りませぬゆえ。
とはいえ、八丸蜂六氏のためにも公開だけはしておきましょう。これは、他
力本願であるのか、自力本願であるのかの違いといえます。すなわち、ア セン
ブラが マシン 語コードへと変換して く れないのであれば、自分で ハン ドア セン
ブルすればよいのです。各セグメント •オーバー ライド•プリ フィックスの マ
シン 語コードは次のようになります。
7/6
CS:
— 2EH
DS:
— 3EH
ES:
-> 26H
SS:
-> 36H
ですから、このコード値をデータとして、命令コード
に含ませてやればよいのです。ここでは、アセンブラの
一般的な疑似命令の DB を使ってみました。
MOV SI, OFFSET DATAA
MOV Dl, OFFSET DATAB
MOV CX, 100 OH
CLD
DB 2EH ;2EH=CS :
REP MOVSW
これで強制的にセグメント•オーバーライド ( DS -> CS ) がなされます。と
ころで、 「 MOVS 」 命令にしても、その他のストリング命令にしても、暗黙指定
の ES を、セグメント•オーバーライドすることはできません。あくまでも、暗
黙指定の DS に対してのみ有効となっていますから注意してください。
なお、 MASM では次の書式でセグメント•オーバーライド•プリフイツクス
が可能となっています。
REP MOVS BYTE PTR [DI],BYTE PTR CS : [SI]
REP LODS BYTE PTR CS : [SI]
REP CMPS BYTE PTR CS : [SI],BYTE PTR [Dl]
REP MOVS WORD PTR [DI],WORD PTR CS : [SI]
REP LODS WORD PTR CS : [SI]
REP CMPS WORD PTR CS : [SI],WORD PTR [Dl]
ここでは 「 DS -> CS 」 というセグメント•オーバーライドを倒]にとりました
が、上の” CS :” の部分を他のセグメント•オーバーライド•プリフイックス命
令に代えることによつて任意の組み合せをとることができます。
さて、これでストリング命令のセグメント•オーバライドが可能になつたわ
けですが、例のコンピュータ卑弥呼に利用した後、秘密が解き明かせるかどう
かについては一切責任は取れませんので悪しからず……。
111
3E
47
十六 i _ a を十進数に
+ 数年前、私は海外で番を張っていました。……というと、おそろしい話に聞こえるで
しょう。でも、これは本当の話です。
私は、ケンカも弱く嫌いです。でも、旅行は大好きです。ユースホステルでは、よく何連泊も
したものです。
ある時、連泊が1力月以上になりました。すると、いつの間にか副番長の肩書きが付きまし
た。やがて番長が日本へもどることになり、なんと私が番長へ昇格したのです。そこでは、日
本人の最長連泊者を番長とする習わしだったのです。
いま、いい年してパソコンに凝っています。マシン語でも〇〜9の数字を画面に表示することが
できるようになりました。それは、 AL レジスタに入れた〇〜9の値を画面に表示するという単
純なルーチンです。
しかし、マシン語上で扱う数値は十六進法です。これを十進法に変換し、一桁ずつ AL レジス
夕に入れられなければ、私のルーチンは役に立ちません。
どうするべきでしょうか。それができないことには、仕事も手につきません。すでに自室へ15
連泊もしています。もう、番長は結構だ……!!
番長ポロ屋敷(宮城 )
■答^- 、
知っています、その話。 スペインのマドリッドの ユースで しょ。 あそこでは
日本人の番長が代々‘火縄式ライター’を安〈売ってくれるというので、私も ノコ
ノコと 出かけて行ったことがあります。大きな日の丸を掲げた べッドの 前で、
弱そうな番長さんがそれを売ってくれましたっけ。
……もう20年近く前の話です。まだ、伝統の番長さんはいるのでしょうか。
どなたか最新情報を教えてください。
さて、十六進数を十進数に直す という 作業は、人間と コンピュータとの 間を
結ぶ重要な仕事です。これがなければ、多くの コンピュータはタダの 箱に逆も
どりです。そうならないように、 プログラマーは その インターフェイスの 役目
を果たさなければなりません。
とりあえず、 AX レジスタにある十六進数を十進数に変換し、一桁ずつメモリ
に入れるというプログラムを組んでみます。
ii8
—AX = 変換した t ヽ十六進数
—「 DX:AX + BX 」 を実行し、 DI レジ
スタで示されるアドレスに AL レジ
スタの値を入れる。 DI レジスタは
+1される
(注) DS = CS と仮定する
「 HDATA 」 に十進数に変換したいデータを入れて コール すれば、そのつど
「 MEMRY 」 に十進データを得ることができます。このあとで 「 MEMRY 」 に
あるデータを表示するのは、簡単なことでしょう。あるいは、このサブ ルー チ
ンにある 「 WARIS 」 で、直接 AL レジスタの値を表示するようにプログラムを
直してもいいでしょう。
マドリッドといえば、マイヨル広場の近くに‘森の家’という安くて評判の食堂
がありました。貧乏旅行者でも、ここに行けばバカ(肉)がバカバカ食べられ
ると、その名声は遠くおフランスの町まで届いておりましたナ。
いつの日か、また放浪の旅をしたい……。
MEMRY
DB
0,0,0,0,0
HDATA
DW
0FFFFH
HENKAN
PROC
MOV
AX, HDATA
MOV
DI,OFFSET MEMRY
MOV
BX, 10000
CALL
WARIS
MOV
BX, 1000
CALL
WARIS
MOV
BXJ00
CALL
WARIS
MOV
BX,10
CALL
WARIS
MOV
[DI],AL
RET
HENKAN
ENDP
WARIS
PROC
XOR
DX,DX
DIV
BX
MOV
[DI],AL
INC
DI
MOV
AX,DX
RET
WARIS
ENDP
H9
3E
48
BCD 数値の加織
7 シは海賊船の船長、グルメ •クックだ。
営業海域はカリブ海。ここには無数の宝島があり、欲に飢えた人間どもが金を持って乗
り込んでくる。ウワッハッハ……。みな、ワシのお得意様よ。
近ごろでは、金が貯りすぎてとても数えきれん。そこで、コンピュータを使って残高を計算で
きるようにしようと思うのだ。もちろん、16ビットのレジスタなんかで間に合うわけがない。
そういう場合、メモリを使うということも知っておる。
しかし、問題がないわけではない。それを画面にどうやって十進数にして表示するかがわから
んのだ。〇〜 FFFF „ (0 〜 65535) までの表示法は最近覚えたのだが……。
イヤ、待てよ。できんということもないナ。メモリどうしの引き算澗45参照)は知っている
から、百万で割り算をするなら、メモリに 0 F 4240„ を入れて引き算を繰り返せばいいのだろう。
でも、面倒くさい話ではないか。いちいち割り算をするなんて。金がドンドン入ってくるのに、
こんな面倒なことやってられるかってんだ。
簡単に十進にする方法はないか。オイ、教えろ!!
カリブの海賊(ネズミーランド)
■答-_
カリブの海賊? まさか、浦安とかロスとかフロリダにいるという例の……。
確かに、あれだけの黄金財宝を数えるとなると、大変なことでしょう。いっ
たい何桁になるのか見当もつきません。割り算のプログラムを組むにしても、
割る数が1兆などという桁になると、それ自体を十六進数に変換するのが大変
です。
そこで登場するのが 、 BCD (Binary Coded Decimal ニニ進化十進数)によ
る計算方法です。これは、十六進数のうち〇〜9までを使用し、 A 〜 F は使用し
ないで 計算しようという考え方です。
例えば、これまでは 12 H といえば十進数では18でしたが、これを十進数の12
と見なすのです。もちろん、見なすのはあなたですから、計算の相手に A 〜 F を
含んだ数値を使ってしまっては意味がありません。
この条件さえ守れば、プログラム的には簡単です。加算命令のあとに 「 DAA 」、
120
減算命令のあとに 「 DAS 」 とひと言入れてやればいいのです。問45の計算例と
比べてみてください。
DATA 0+ DATA 1 DATA 0 - DATA 1
DATA 0 DB 32 H ,20 H ,58 H
DATA 0 DB 32 H ,20 H ,58 H
DATA 1 DB 13 H ,50 H ,88 H
DATA 1 DB 13 H ,50 H ,88 H
KEKKA - DB 0,0,0
KEKKA DB 0,0,0
ADD 01 PROC
SUB 01 PROC
PUSH DS
PUSH DS
PUSH ES
PUSH ES
MOV AX,CS
MOV AX,CS
MOV DS,AX
MOV DS,AX
MOV ES,AX
MOV ES.AX
MOV SI,OFFSET DATA 04-2
MOV SI,OFFSET DATAO + 2
MOV BX,OFFSET DATA 1 + 2
MOV BX,OFFSET DATA 1 + 2
MOV Dl,OFFSET KEKKA + 2
MOV Dl,OFFSET KEKKA + 2
CLC
CLC
STD
STD
MOV CX ,3
MOV CX ,3
ADDLP : LODSB
SUBLP : LODSB
ADC AL ,[ BX ]
SBB AL ,[ BX ]
DAA
DAS
STOSB
STOSB
DEC BX
DEC BX
LOOP ADDLP
LOOP SUBLP
POP ES
POP ES
POP DS
POP DS
RET
RET
ADD 01 ENDP
SUB 01 ENDP
<- CX = 桁数
なお、 「 DAA 」、「 DAS 」、 共に演算結果は AL レジスタに求めるという条件付
きですから注意してください。
計算の終了した時点で、 「 KEKKA 」 にはそのまま十進数として読めるような
形で答が入っています。画面に表示する時には、それぞれの値を上位/下位に
分けて表示すればいいのです。
121
上位の値を AL レジスタへ 下位の値を AL レジスタへ
MOV
AL # [BX]
AND
AL, 00001111 B
MOV
AL,[BX]
MOV
CL,4
SHR
AL,CL
(注)どちらも DS : BX レジスタで表示したい数値のあるアドレスを指定したものとする
これで、割り算による手間が省けるとともに、桁(兆の位とか億の位…等)
を意識しないで数値を表示することができるわけです。
ところで、カリブの海賊は有名だけど、ネズミーランドっていうのは???
122
49
データの茄顾
めての質問です。雑誌に投稿するのが趣味の高校3年ですが、これからは受験勉強のた
^め投稿はしばらく休まなければなりません。でも、これまでに某誌に2回も自分の作品
が発表されたことがあるんですよ (BASIC + マシン語だよ〜ン)。
マシン語は、おもにキャラクタの表示部分なんだけど、左右反転したパターンを見るたびに、
メモリがもったいないなァと思います。
インストラクシヨン表で、左右反転ができるような命令を捜してみましたが、どうもなさそう
です。
なんとか、この無駄を解決する方法はありませんか。できれば、受験の前にこのモヤモヤを取
り除きたいなァ。
投稿マニア(徳島)
■答- •
さすが、投稿マニアを自称するだけあって、鋭い質問ですね。データは少な
く、プログラムは短く、そして速く……マシン語の技術の差は、ここに現れる
のです。
すでに、このことに目覚めているからこそ、これだけの質問がでるのでしよ
う。おそらく、受験勉強がなければ自力で解決できるだけの実力があるはずで
す 。
とりあえず、質問の内容が具体的でないので、例をあげて解決することにし
ます0
(例)
A しレジスタ = EAh
AL レジスタ =57 h
左右反転のパターンを作るには、1つのデータを図のように左右対象に入れ
換えなければなりません。残念ながら、この命令はいくらインストラクション
表を捜してもありません。また、論理演算命令を繰り返しても作ることはでき
ません。
ということは、プログラムで反転データを作るしかないわけです。そこで、
キャリーフラグを利用して次のようにします。
MOV
CX,8
LP01 : RCL
AL,1
RCR
AH,1
LOOP
LP01
MOV
AL, AH
AL レジスタの値を左回りにローテートさせると、7ビット目の値がキヤ
リーフラグに入ります。次に、キヤリーフラグの値が AH レジスタの7ビット
目に入るように AH レジスタを右にローテートさせます。これを8回繰り返す
わけです。
キヤリーフラグの動きは、インストラクシヨン表を見ればわかるでしょう。
問題は少々時間がかかることで、速度を追求する場合には利用できないかもし
れません。それを考慮した上で使えば、結構役に立てられるはずです。
でも、この程度の内容の命令は最初から用意しておいて欲しいものですネ。
124
閩
50
実用できる左右反転ブログラム
P これは「ピー」と読みま p 。 こちらは、ミニ独立国家ピータンで P 。 わが国の憲法はた
〇だひとつ、言葉の最後に p を付けることで P 。
では、質問で P 。 最近、データを反転するテクニック(問49参照)を覚えたのですが、どうも
実用性に乏しいような気がするので P 。 その理由は速度で P 。 1バイトのデータを反転するの
に、
<-4
—2 X 8=16
—2 X 8=16
—17 X 7+5 = 124
で、トータル162クロックもかかっていま P 。 たった1バイトならともかく、大量のデータを
反転するとなると問題で P 。 しかも、そのために CX レジスタを破壊しなければならないので
P 0
これでは、現実には使いたくても使えないということになってしまいま P 。 もっとうまい方法
があると、とても便利でハッピーな気分になれそうで P 。
ピータン国王(岩手)
■答-《
さすが、国王。単にプログラム•テクニックを知っただけでは満足せず、そ
こに実用性を求めていま P 。 おそれ入りましたで P 。
確かに、1バイトを反転するのに162クロックもかかるのは問題でしょう。
グラフ ィッ クなどはデータの山ですから、リアルタイム.ゲームに応用するの
はほとんど不可能とも言えます。
そこで、少々メモリは必要ですが、とっておきの秘法を紹介します。
この場合、 DS レジスタには、 RDATA の存在するセグメント値が、あらかじ
め設定してあるものとします。
これで、実行速度は1バイトにつき15クロックですから、147クロックも速
くなったことになります。また、 AL レジスタを反転するのに CX レジスタを必
MOV
CX ,8
LP 01 : RCL
AL ,1
RCR
AH ,1
LOOP
LP 01
MOV
AL,AH
125
RDATA LABEL BYTE
DB 00H.80H,40H,0C0H,20H,0A0H,60H,0E0H
DB 10H.90H.50H.0D0H,30H.0B0H.70H.0F0H
DB O8H,88H,48H.OC8H,28H.0A8H,68H,0E8H
DB 18H, 98H, 58H,0D8H.38H, 0B8H.78H.0F8H
DB 04H.84H,44H,0C4H I 24H,0A4H,64H,0E4H
DB 14H,94H.54H,0D4H.34H.0B4H.74H,0F4H
DB 0CH.8CH.4CH,0CCH,2CH.0ACH.6CH.0ECH
DB lCH.9CH.5CH.6DCH.3CH,0BCH f 7CH.0FCH
DB O2H,82H.42H,OC2H,22H,0A2H f 62H,0E2H
DB 12H, 92H, 52H, 0D2H, 32H, 0B2H,72H,0F2H
DB 0AH.8AH,4AH,0CAH,2AH,0AAH.6AH.0EAH
DB 1AH, 9AH, 5AH,ODAH, 3AH, OBAH.7AH,OFAH
DB 06H.86H,46H,0C6H,26H,0A6H.66H.0E6H
DB 16H.96H f 56H.0D6H,36H,0B6H,76H.0F6H
DB OEH,8EH, 4EH, OCEH. 2EH, OAEH,6EH,OEEH
DB lEH,9EH,5EH,ODEH.3EH,OBBH,7EH,OFEH
DB OlH,81H, 41H, OC1H, 21H,0A1H,61H,0E1H
DB 11H.91H,51H.0D1H,31H.0B1H.71H,0F1H
DB 09H,89H,49H.0C9H f 29H,0A9H.69H.0E9H
DB 19H,99H.59H.OD9H.39H,OB9H.79H,OF9H
DB O5H,85H,45H,0C5H,25H,0A5H,65H,0E5H
DB 15H.95H,55H,OD5H,35H.OB5H.75H.OF5H
DB 0DH,8DH,4DH.0CDH,2DH,0ADH.6DH.0EDH
DB 1DH, 9DH, 5DH f ODDH, 3DH, 0BDH.7DH.0FDH
DB 03H.83H.43H.0C3H.23H.0A3H.63H.0E3H
DB 13H.93H.53H.0D3H,33H.0B3H,73H.0F3H
DB 0BH.8BH.4BH.0CBH,2BH.0ABH,6BH.0EBH
DB 1BH, 9BH, 5BH,ODBH, 3BH,OBBH,7BH,OFBH
DB 07H,87H,47H.0C7H, 27H,0A7H.67H.0E7H
DB 17H.97H,57H.OD7H.37H,OB7H,77H.OF7H
DB 0FH.8FH.4FH.0CFH,2FH,0AFH,6FH.0EFH
DB 1FH.9FH.5FH,0DFH,3FH.0BFH.7FH.0FFH
MOV BX,OFFSET RDATA
XLAT
(注) XLAT:AL — DS :[ BX + AL ]
要としませんので、ループの中にこのまま組み入れることも可能です。また、
ループ中に組み込む場合、 BX レジスタの 初期値をループに入る前に設定すれ
ば、1バイトにつき11クロックですから、さらに変換スピードはアップします。
アイデアがシンプルなだけ、実用性は逆に高くなったと言えるでしょう。大
いに活用してください。
では、国王。バイ P ……。
126
/ オレ様は地獄の番人、閻魔大王だ。グワッハッハ……!!
オレ様の前でウソなどついてみろ。アッという間に、この大きな‘やっとこ’で舌を抜いてしま
うからナ。オレ様は、人間の話す言葉から、それがウソか真実か、簡単に見抜くことができる
のだ。
この間も、「手みやげに金の延べ板を持参してきました」と、オレ様に鉛に金メッキをしたま
がい物を渡そうとしたヤツがおってな。もちろん、血の池経由の針山行きよ。バカ者めが……。
ところが、このオレ様にも最近弱点ができてしまったのだ。それは、なんとマシン語を話題に
する相手のことだ。オレ様も必死になってマシン語を勉強したのだが、なかなか思うように上
達せんのだよ。
今日も、「フラグの中には AF フラグなど、ユーザーには関係のないフラグがある」などと言わ
れてしまい、どうにもわからんで困っておる。なんとか、オレ様の役目も理解して、親切にご
指導願いたい。
閻魔大王クッパ(地獄一丁目)
■答--
こわそーッ。でも、ここでウソなど教えたら、いつの日かお目にかからなけ
ればならな〈なった時、血の池経由の針山行きなどとされてしまいそうです。
それだけは、なんとしても避けなければ……。
とりあえず、 AF フラグの内容とは次のようなものです。
• AF (補助キャリー)フラグ
演算の結果、その演算がバイト単位であればニブル、ワード単位ならばバイト
での桁上がり、または桁借りが生じた時にセットされる。
このフラグは、 BCD 演算や十進 ASCII 演算における演算補正のために用意
されているものです。したがって、これらの演算に関係のない命令によって変
化しても、基本的に意味はありません。ユーザーがジャンプ命令等で利用でき
ないようになっているのも、特に必要がないからだといえるでしょう。
しかし、 DAA 命令によっても変化する AF フラダは、利用できるなら利用し
127
たい時がないわけでもありません。例えば、特定の桁が変化したかどうかを調
ベるという場合など、 AF フラグがキャリーフラグとともに利用できると便利
です。
このような場合でも、 AF フラグがフラグレジスタの中にある限り、どうやつ
ても調べることはできません。そこで、 AF フラグの存在するフラグレジスタの
下位8ビットを、次のように AH レジスタに移動すれば調べられます。
—フラグレジスタの下位8ビツトを AH レジスタへ
— AF フラグのチェック
また、あまり関心しませんが次のような方法も考えられます。
LAHF
TEST
AHJOH
JNZ
XXXX
—フラグレジスタの値を AX レジスタへ
— AF フラグのチェック
この方法であれば、もちろん上位8ビットのフラグも調べることはできます
が、いずれにしてもそれほど必要になることはないでしょう。要するに、やむ
を得ない時には、こういった奥の手もあると覚えておけばいいという程度のこ
とです。
これらは、決してウソの説明ではありません。本当に、本当ですとも……閻
魔大王クッパさま……。
PUSHF
POP
AX
TEST
ALJOH
JNZ
XXXX
128
閩
52
rCMP DS - ESJ を実現
m 春光うららかな今日このごろ、皆様にはますますご隆盛大慶に存じます。
わが輩は、明治生まれの真空管技術者でござりまする。わが輩も、_時期は時代の最先端をい
く花形技術者としてもてはやされたのでござりまするが、それも今や過去の夢物語でありま
そこで一念発起、パソコンを購入しマシン語なるものにチヤレンジしたのでござりまする。結
構、色々な命令があるものでござりますな。これまでの調べで、他のレジスタに比べて、セグ
メント.レジスタを操作する命令が少ないことも判明しております。
セグメント•レジスタである以上、ある程度はやむを得ないのかもしれぬが、それにしてもセ
グメント • レジスタ用の CMP 命令がないのはどういうことでござろうか……。
つまり、 「CMP CX,DS」 とか 「CMP DS,ES」 という命令が欲しいのでござりまする。いく
らセグメント•レジスタとはいえ、この程度の能力がないようでは、なにかと不便で仕方がな
いのでござりまするな。
よろしくお頼もうすでござる。
敬具
明治キメラ(長野)
■答- •
これはこれは、ご丁寧なご質問ありがとうでござりまする。パソコンという
共通の話題がある限り、「明治は遠くなりにけり」なんて死語でござりまするな。
確かに、セグメント•レジスタ用の CMP 命令がないというのは不便なことか
もしれません。例えば、セグメント•レジスタをワーク•レジスタとして使う、
なんていう場合もありますから。
しかし、命令として存在しないものは自力で作ればいいのです。そもそも大
した命令がないのがマシン語ですから、ないものはプログラムで作るのが当然
ともいえます。さっそく、質問にある2つの命令を実現できるように、マクロ
定義をしてみました。
129
CMPR1R2 MACRO
REG 1,REG2
PUSH
AX
PUSH
BX
MOV
AX # REG1
MOV
BX,REG2
CMP
AX,BX
POP
BX
POP
AX
ENDM
このようにマクロ定義すれば、ほとんどのレジスタが使えますから、 いつで
もセグメント•レジスタの CMP 命令として利用することができます。質問を例
にとつて、ここで定養したマクロの使用方法を次に示します。
(CMP CX.DS) の場合
この例では CMP 命令でしたが、 CMP 命令に限らず、他の命令、例えば ADD
とか SUB などをマクロ定義してみてはいかがでしょうか。では、がんばってく
ださいでござりまする……。明治キメラ殿。
CMPR1R2 CX, DS
JGE * * * *
(CMPDS.ES) の場合
CMPR 1 R 2 DS'ES
JNE 氺氺ホ氺
13〇
I
53
「CMP DX : AX,
* J を類
-i— 都〜ォ、大原三千院 . 。
M うちは京の舞妓どす。優雅に歌など歌っている姿を想像して、うちの美しさを味わって
おくれやす。
でも、これはマイコンが趣味でドス (DOS = Disk Operating System) を作りたいという気持
ちが高まって、いつの間にか自分のことを舞妓はんと思うようになったのが本当の話どす。
勘違いされる前に宣言しておきやすけど、一応正真正銘の女の子どすよってに、気色ワル〜イ
とかは言わはらんようにお願いしやす。ちなみに、うちの話す舞妓はん言葉もメチャクチャど
すェ。なにしろ、生まれは関東どすから……。
いま、あるプログラムで、 DX に上位16ビット、 AX に下位16ビットを格納した、32ビットの数
値とイミ—ディエイト値の比較 「CMP DX : AX, 12345678 HJ という内容を実行したいのどす
が、うちの実力ではどうにもわからんのどす。
こういう場合、いったいどうしたらいいのどす?困ってしまうどす。ア〜ァ、それにしても
マイコン以上に舞妓はん言葉は難しいどすねェ。
ニセ舞妓(京都)
■答- -
言葉の最後に「どす」を付ければ舞妓さんというのも、なにかモノスゴイ勘
違いのような気がしますどす。とりあえずは、正真正銘の女の子ということが
唯一の救いかもしれませんどす。
さて、この命令に相当するプログラムは、次のようにすれば作ることができ
ます。
CMP 命令の動作は、第ーオペランドから第ニオペランドを減算し、その計算
結果をフラグへ反映させるものです。動作としては、第ーオペランドの値が命
令実行後も元のままであること以外は SUB 命令と同じです。したがつて、レジ
スタを保存してやれば、このように32ビット CMP 命令が簡単に作れることに
なるのです。
ここではプロシージャとして記述しましたが、マクロ定義をしておくのも1
つの方法でしよう。
131
CMPDA
PROC
PUSH
AX
PUSH
DX
SUB
AX,CS:DATA
SBB
DX,CS:DATA+2
POP
DX
POP
AX
RET
CMPDA
ENDP
DATA
DW
5678H
DW
1234H
132
閩
54
レジスタペアの NEG 命令
— こは エジン バラ ……。イギリス北部、スコットランドにある美しい町です。申し遅れま
一 したが、ポクはイギリス国内をヒッチハイクによって旅している者です。
慣れてしまえばどうということのないヒッチハイクも、最初は親指を立てて右手を上げるの
にとても勇気が入りました。一台、また一台……と車が通過するたびに、ポクには絶対に止
まってくれないのではないかという不安感が頭をかすめたものです。
1時間ほどして、ようやく一台の乗用車が止まってくれた時は、ポーッとして一瞬われを忘れ
たほどです。でも、それがきっかけとなってヒッチハイクのコツがわかり、今ではマナーをわ
きまえた一流のヒッチハイカーです。
それはいいとして、忘れられないのが日本に置いてきたコンピュータのこと。というより、
せっかく覚えたマシン語のことです。だから、頭の中はいつもマシン語でいっぱいです。車が
止まってくれない時は、もちろんマシン語のことを考えています。
「 NEG 」 というマイナスの値を作る命令がありますね。ある時、あれの32ビット版はどうやっ
たらいいか。これを考えていたら、右手を上げるのをすっかり忘れてしまったことがありま
す。
おかげで、車は止まらないわ、雨は降ってくるわ……で、さんざんな目にあってしまいました。
どうか、気分よくヒッチハイクができるように教えてください。
ヒッチくん(エジンバラ)
■答- •
日本ではヒッチハイクの習慣はあまりありませんが、 ヨーロッパ などでは若
者の移動手段として立派に市民権を得ています。目的地にいつ到着するかわか
らな いという 不確実な点も、若者の気ままな旅に合っているのかもしれません。
ヒッチハイクのコツは、まず郊外の街道筋まで出るということ。例えば、銀
座や新宿のような場所では成功しません。そして、車が止まってくれたら、急
いで車のほうへ走り寄り、行き先をハッキリと言います。行き先が違えば、残
念ながら乗るのはあきらめなければなりません。運よく乗せてもらうことがで
きたなら、相手に不快感や不安感を与えないようにするのも大切なことです。
乗せて楽しかったと思われるようになれば、もう一流のヒッチハイカーでしよ
う。
133
私は五円玉をたくさん用意しておいて、降りる時に記念に一枚渡しました。
外国には穴の開いたコインが少ないので、結構喜ばれたものです。おっと、あ
まりヒッチハイクの秘伝ばかり書いていると、肝心の質問を忘れてしまいそう
なので、ここではこれくらいにして おきましょう。
16ビットの 「 NEG 」 は問14で紹介しましたが、32ビット用の 「 NEG 」 は命
令として存在していません。そこで、ブログラムで作ることになります。デー
夕は上位16ビットが DX へ、下位16ビットが AX へあるものとします。
NEG32 :
SUB AX,1
SBB DX,0
NOT32 :
NOT AX
NOT DX
RET
初めに 、 rSUB AX ,1」 としていることに注意してください。これを 「DEC
AX 」 と置き換えてしまうと、とんでもないことになります。というのも、 「 DEC 」
や 「 INC 」 命令では、キャリー•フラグが変化しないため、次の 「SBB DX ,0 J
という命令が無意味になってしまうからです。
また、プログラムのラベルを見ておわかりのように、最初の減算命令を省く
ことにより 「 NOT 」 の32ビット版とすることができます。
ちなみに、ビット単位で 「 NOT 」 と 「 NEG 」 の違いを見ると、次のようにな
ります。 AL レジスタの値は000011 11 B = 0 F H と仮定します。
NOT AL: 11110000 B = F0„ (数値上は 「XOR AL,0FFH」 と同じだが、
フラグ変化が違う)
NEG AL: 11110001 B = F 1 H (NOT した値に + 1したもの)
両者とも、内容をよく理解した上で使用することが大切です。フラグ変化の
違いなどもよく確認しておきましょう。気分よくヒッチハイクするためにも
134
閩
55
ジャンプ代わりにリターン
Ai - 手 5 八玉……。
7 C どうだ!!これがワシの発明した戦法「玉先導」の一手目だ。その先はまだ秘密で教え
られないが、この手で動揺した棋士は皆あわてふためいて、結局は負けてしまうことになるの
だ 0 ワッハッハッハ!!
ワシはプロの棋士、相手もプロ……。といっても、相手のプロはプログラムで動くコンピュー
夕という意味だがな。もちろん、ワシがプロの棋士というのも、プログラムで動く棋士という
意味だ。
おっと、正確にはワシはそのプログラマーというわけだ。できるだけ強いプログラムにするに
は、メモリを効率よく使って思考ルーチンを強化しなければならぬ。実は、プログラムの一部
に50箇所にジャンプする部分がある。当然、テーブルは使っている。
TABLE
DW
PROOO, PROOl , …… • PR048, PR049
MAINP :
MOV
BX,OFFSET TABLE
SH し
AX,1
ADD
BX,AX
JMP
CS:[BX]
プログラムの概略は以上なのだが、それぞれのルーチンからは 「 MAINP 」 へジャンプしても
どってくるようになっておるのだ。単純に計算しても 「JMP MAINPJ が50個はあるという
ことだ。そのほかにも、条件分岐でもどるものもあるので、実際には1〇〇箇所以上から 「 MAINP 」
へジャンプしてくるのだ。
こういったルーチンがいくつかあるので、これに要するメモリもバカにならない。なんとか省
メモリ化できないだろうか。
白夜の棋士 (静岡)
■答---
コンピュータで本当に強い将棋プログラムができたら、つまり本物のプロ棋
士と互角に戦えるようなレベルになったら、こんな痛快なことはないでしょう
ね0
なぜかというと、そこまで強いプログラムになると、理論上は常に最善手を
135
指してくるからです。そうすると、敗着の手を指す恐れのある人間の頭では、
アツという間にコンピュータに勝てなくなってしまうでしょう。では、そんな
コンピュータどうしの勝負はどうなるのか、それを早く見てみたいものです。
しかし、現在のコンピュータのレベルでは、大局観という要素があまりない
ので、当分はお遊びソフトの域を出るのは難しそうです。
さて、質問にあるようなメインプログラムへの大量ジャンプですが、こうい っ
たケースにはアチコチで遭遇します。省メモリを目指す場合には、次のような
テクニックを覚えておくと便利です。
— MAINP のアドレスを、
もどりアドレスとして
スタックへ入れておく
つまり、 「 MAINP 」 をリターンアドレスとしてスタックへ退避しておくので
す。こうすれば、それぞれのルーチンから JMP 命令でなく RET 命令で
「 MAINP 」 へジャンプさせることができます。
この時注意しなければならないのは、各ルーチン先で場合によっては
「 MAINP 」 へもどらないことがある場合です。このような場合、スタックヘリ
ターンアドレスを退避してあることを忘れてしまうと、 SP が狂って暴走する
危険性があります。したがって、 RET 命令で直接 「 MAINP 」 へもどらない時
は、 SP 合わせのダミーとして 「POP AX 」 などを実行するか、 SP +2 として
SP を元にもどす必要があります。
このことにさえ注意すれば、このテクニックの活用の場は結構多いはずです。
うまく活用して、本当に名人級の将棋ソフトを作ってください . 。
TABLE
DW
PROUD, PR0Q1,.,PR048 / PR049
MAINP:
:
MOV
BX,OFFSET MAINP
PUSH
BX
MOV
BX,OFFSET TABLE
SHL
AXJ
ADD
BX,AX
JMP
CS : [BX]
J36
閩
56
ビット飜の縦方向コピー
ワァ〜ァ . 。眠たい眠たい . 。
小 プログラマーは眠たい。とにかく眠たい。おっと、これは失礼。私は、某ソフトハウス
でゲーム制作のプログラム • アシスタントをしている者です。
アシスタントといっても、自分の受け持ったルーチンは責任を持って組まなければなりませ
んから、手伝いというような甘い考えは通用しません。しかし、恥ずかしながら私はプログラ
マーとしてはまだまだ未熟者です。
ところで、私が今やろうとしているのは、 AL レジスタのビット0から7までのビット情報を、
メモリのビット N へ80バイトごとにコピーするという作業です。つまり、横方向のビット情報
を縦方向にコピーすることなのですが。どうも、プログラムまで寝たまんまです。どうしたら
いいでしようか?
それにしても、ホワァ〜ァ……眠たい眠たい……。
眠りプログラマー (福島)
■答--
ホワァ〜ァ……眠たいのは、こちらも同じこと。まったく、いくら寝ても眠
たさは解消しません。今も、必死に眠たさをこらえて質問に答えているところ
です . 。
それでは、こちらの眠たさはこらえて、この横に寝たまんまのブログラムを、
起こして縦にしてみせましょう???
実は、これはビット情報を縦方向へコピーする基本形なのです。これを応用
すると、例えばグラフィック VRAM 上に展開した横向きの戦闘機を、縦に向き
を変えて表示するという芸当ができるわけです。もっとも、高速処理が要求さ
れるリアルタイムゲームでは、あらかじめデータとして持たせなければなりま
せんが……。
ホワァ〜ァ . 。本当に眠たくなってしまった、ムニャ . 。
137
ADR 01 DD ASEG 1 : AREA 1
BITN DB 7
AWAKE PROC
PUSH
MOV
MOV
ROL
ROL
LDS
MOV
m / u : AND
SHR
JNB
OR
AWOl :ADD
LOOP
POP
RET
AWAKE ENDP
DS
DX ,0 FE 01 H
CL,CS : BITN
DHXL
DL,CL
SI , CS : ADR 01
CX # 8
[ SI],DH
AL ,1
AWA 01
[ SI],DL
SI ,80
AWAL 1
DS
138
57
ブロック比較について
、ゲ、ゲゲゲのゲーッ . 。
^ 近ごろ、ウイルスというコンピュータを悩ます妖怪がはびこっているそうだが、そんな
ことで困っている人は、この正義のコンピュータ妖怪「ゲゲゲの Q 太郎」に連絡してください。
連絡方法は、お近くのゲゲゲ•ネットワークへ申し込めばいいようになっています。あなたの
システムに入り込んで、即座にウイルス妖 *1 圣をやっつけてあげましよう。
……という看板を出したのはいいけれど、実はまだ本物のウイルス妖怪にはお目にかかった
ことがありません。つまり、この看板は「出たとこ勝負」のバクチなのです。とはいえ、とり
あえずは正体不明の妖怪対策も考えておかなければなりません。
たぶん、ウイルス妖怪退治には値をサーチする命令や、ブロック比較命令が欠かせないでしよ
う。これらの命令としては、次のようなものがありますが……。
SCASB : AL と ES :[ DI ] とを比較し、 DF =0 なら Dl —DI + 1 、DF = 1 なら DI — DI — 1を実
行する。 REP ( REPZ ) または REPNZ 命令と組み合わせると、 CX レジスタを力
ウンターとした連続比較が可能となる。
SCASW : AX と ES :[ DI ] とをワード単位で比較し 、 DF = 0 なら Dl —DI + 2 、DF = 1 なら DI
— DI -2 を実行する。 REP ( REPZ ) または REPNZ 命令と組み合わせると、 CX レ
ジスタをカウンターとした連続比較が可能となる。
CMPSB : DS :[ SI ] と ES :[ DI ] とをバイト単位で比較し 、 DF = 0 なら DI — Dl + l、SI —
SI + 1 を、 DF =1 なら Dl — DI — 1 、 SI — S 卜1を実行する。 REP ( REPZ ) または
REPNZ 命令と組み合わせると、 CX レジスタをカウンターとした連続比較が可
肯 g となる。
CMPSW : DS :[ SI ] と ES :[ DI ] とをワード単位で比較し、 DF =0 なら DI 卜 DI + 2 、SI —
SI + 2 を、 DF =1 なら DI 卜 DI — 2、 SI — SI -2 を実行する。 REP ( REPZ ) または
REPNZ 命令と組み合わせると、 CX レジスタをカウンターとした連続比較が可
育 g となる。
(注) DF : ディレクシヨン•フラグ
実は、どうも実行結果やフラグの見方がわからないのです。コンピュータの正義のために、正
しい利用法を教えてください。
ゲゲゲの Q 太郎(正マ界)
■答-^
ゲゲゲの Q 太郞 . ? どこかで聞いたような名前です。頼りになる妖怪と
139
頼りにならないお化けが合体したような、なんとも妙な雰囲気が漂っています
が、質問からするとまだまだ実力不明の妖怪のようです。
w 、 B とも基本的な考え方は変わりありませんから、ここではバイト単位の
命令について説明をします。まず SCASB ですが、これを実行するとフラグ以
外のレジスタは次のように変化します。
DI —DI + 1
REP (REPZ) または REPNZ と組み合わせた連続サーチの場合は、次のよ
うになります。
DI
DI +1
CX
CX - 1
これは、 AL レジスタと ES :[ DI ] が同じであろうとなかろうと、その結果に
関係なく実行されるものです。したがって、 SCASB 命令で AL = ES :[ DI ] と
なった時点(命令実行後)の DI レジスタの値は、+1されていることになりま
す。もし、 AL 二 ES :[ DI ] となっている DI レジスタを求めたいのであれば、
SCASB 命令の後で 「DEC DI 」 を実行しなければなりません。
次に、フラグ変匕についてですが、これらの4つの命令はレジスタの増減を
伴った CMP 命令をレジスタ単位で行うか、ブロック単位で行うかであり、基
本的動作は CMP 命令と同じものです。
また、 REP(REPZ) または REPNZ と組み合わせた場合には、 CX レジスタ
をカウンターとして、 CX — CX — 1 を実行し、 CX 二〇になるまで連続比較され
ます。 REP(REPZ) ではゼロフラグが立っている間命令が継続され、ゼロフラグ
がリセットされると終了します。 REPNZ では、そのフラグによる動作が逆にな
ります。
試しに、 REPNZ (ゼロ フラグが立っていなければ命令を続ける)と組み合わ
せた SCASB 命令を考えてみましょう。
この例では、実行後にゼロフラダが立っていれば AL 二 ES : [ DI ] となって命
令を終了したことになり、ゼロフラグが立っていなければ CX = 0 となって命令
14〇
—デイレクシヨンフラグ =0 とする
<-DI レジスタに初期値をセツト
— ES=CS
— サーチ 回数を セツ ト
— サーチ 文字を セツ ト
—AL の文字を サーチす る
を終了したと判断できますから、文字’ A ’ の存在の有無をゼロフラダで調べるこ
とができるわけです。
なお、 CX 二 CX— 1、 DI 二 DI + 1 は文字’ A’ の存在にかかわらず、命令の1サイ
クルで実行されることに注意してください。
次に CMPS 命令ですが、これは、 SCAS 命令が AL または AX レジスタと
CLD
MOV
Dl,OFFSET STRING
MOV
AX,CS
MOV
ES,AX
MOV
CX ,10
MOV
AL / A ’
REPNZ
SCASB
ES :[ DI ] とをバイトまたはワード単位で比較したのに対して、 AL 、 AX の部分
を DS :[ SI ] に置き換えて考えることができます。この場合、 SI レジスタは自動
的に更新されます。
それにしても、いつの間にコンピュータの中に「正マ界」なんていう世界が
できたのでしようか . 。
ip
||
58
SCASB 齡咖果的用法
JL^ イ、ゲゲゲの Q 太部!!勝手にウイルス妖怪退治なんて始めるのはやめてくれ。オイラ
1 のように正しいコンピュータの発展を願っている者には、はなはだ迷惑な話だせ。だい
たい、おまえはいつも正義面して厚かましいゾ!!
本当の正義の味方とは、オイラのことだ。ウイルス妖怪だって立派なプログラムなんだから
な。コンピュータから見れば、有難いお客様だっていうことを忘れないでくれ。あんまりウイ
ルス妖怪をいじめるなら、オイラがウイルスになって戦ってもいいんだゼ。
ところで、ゲゲゲの Q 太郎の質問に答えたんだから、オイラの質問にもまじめに答えてくれよ
な。オイラのは Q 太郎と違って、高級な質問だせ。やはり、ある値があるかどうかを調べるん
だが、チェックする値が複数なんだ。
例えば、 DATA1:STRING から、100 0 H バイトの範囲で、アスキーコードの’ A’ ’D’ ’F’ ’K 1 のどれ
かが含まれているかどうか、それを調べようというんだ。
これには、 SCAS や CMPS 命令は使えないよな。やっぱり、 CMP 命令で1つひとつチェック
するしか方法はないだろうな……。
でも、チェックする内容が多くなると、 CMP 命令というのは結構大変なんだせ。オイラにも
うまい方法を教えてくれ。
ドブねずみ男(邪マ界)
■答- •
ゲゲゲの Q 太郎氏から質問があった時、きっとこの手の人物(妖怪)からも
質問が来ると思っていました。それが、まさかこんなに早くやって来るとは
……〇ア然!!
なにはともあれ、ここはまじめに答えなければなりますまい。もはや、誰が
正義で誰が悪なのか、こちらにはサッパリわかりませんから。
まず、この質問の内容をそのままプログラム化してみましょう<
CLOOP:
MOV
AX,DATSEG1
MOV
ES.AX
MOV
Dl,OFFSET STRING
MOV
CX, 1000 H
: CMP
BYTE PTR ES:[DI],’A,
JE
CPEND
142
CMP BYTE PTR ES :[ DI ],’ D ’
JE CPEND
CMP BYTE PTR ES :[ DI ],, F ,
JE CPEND
CMP BYTE PTR ES :[ DI ]/ K ’
JE CPEND
INC DIEND
LOOP CLOOP
CPEND :
内容のわりには、プログラムが大がかりです。そこで、なぜ SCAS 命令が使
えないという結論を出したのか考えてみましょう。これは、おそら〈比較しよ
うとする値 (’ ADFK ’) が AL レジスタになければ SCAS 命令は使えないと判断
したためだと思います。
しかし、ここはコロンブスの卵で発想を転換したいところです。つまり 、 AL
レジスタには DSTAl : STRING のメモリ内容を入れ、比較しようとする値(’
ADFK ’) をメモリ側に置くのです。文章ではわかりにくいので、実際にプログ
ラムを組んでみます。
CDATA DB ’ ADFK ,
MOV AX,DATSEGl
MOV ES.AX
MOV DS,AX
MOV SI,OFFSET STRING
MOV DX , 1000 H
CLD
CLOOP : LODSB
MOV Dl,OFFSET CDATA
MOV CX ,4
REPNZ SCASB
JZ CPEND
DEC DX
JNZ CLOOP
RET
CPEND :
143
こうすれば、たとえチェックする値や1唄序を変更する場合でも、 「 CDATA 」
の内容や並びを変えるだけで簡単に変更できます。チェックする数が多くなれ
ばなるほど、このブログラムの簡略さが活きてくるでしょう。
ドブねずみ男氏が、どのような目的でこの複数サーチ • プログラムを利用す
るのかわかりませんが、あまりコンピュータ内部でモメないようにお願いしま
す。めったに出てこないウイルスより、身近な暴走のほうが困りますから 。
144
閩
59
SCASB 命^と テーブル
ラ〜ッ!! Q 太郎にドブねずみ男。ケンカをするでにやい。少しは、わしの立場も考え
」てくれにや、人間さまがコンピュータを嫌いになってしまうじやろが。
わしか、わしはこの世界の長老‘目ン玉おやじ,に決っておるじやろ。初代コンピュータが巨大
な箱としてこの世に生まれてから数十年、絶えることなくバグを繁殖させ、そしてそれを食べ
続け、バグとともに生きてきたのじやよ。
おまえらみたいに、ポッと出の妖怪とはレベルが違うからのう。ましてや、ウイルスなんぞは
わしの歴史に比べたら、ひよつこもいいところじや。フォッフォッフォ……。
んにやから、わしの質問はドブねずみ男なんか問題にならんほど高級じや。マ、少し似ておる
といえないこともないがの。実は、コールすると押されたキーのアスキーコードを返す
「 KSCAN 」 というルーチンがあるんじや。その中にな、’ A ’ ’ D ’ ’ F ’ ’ K ’ のどれかが含まれてい
れば、それぞれに応じたルーチンへジャンプさせようというのにやよ。
CLOOP :
CALL
KSCAN
CMP
AL ,, A ’
JE
CCDTA
CMP
AL ,’ D ,
JE
CCDTD
CMP
AL ,’ F ’
JE
CCDTF
CMP
AL / K 1
JE
CCDTK
JMP
CLOOP
これでは、さすがに SCAS 命令は使えないじやろ。こればかりは、 CMP 命令で1つひとつ
ジャンプさせるしか手はあるまい。じやがな、チェックするキーの種類が多くなつてくると、
これも大変なことなんじや 。
目ン玉おやじ(本マ界)
■答- *
とうとう出てきましたか。ウワサには聞いたことがありますが、まさか本物
の‘目ン玉おやじ’まで登場してくるとは!!
145
コンピュータの歴史はバグの歴史とも言われていますが、バグとは人間でい
うなら痛みのようなもの。もしも、人間が痛みを感じなければ、ケガをしよう
が骨折しようが、死んでも気がつかないという悲惨な状況になってしまいます。
こんな惨劇を未然に防ぐバグ 。ありがたいバグを育ててくれる‘目ン玉お
やじ’に心から感謝をしましょう。
さて、今回のようなケースは意外と多く出てきます。問27にあったようなテー
ブルが利用できればいいのですが、チェックする内容が連続していないので、
そのままでは利用できません。
チェックする数が少なければ CMP 命令で もいいのです が、多くなること も
考えて次のような手法があることも知っておくべきでしょう。
—• AL レジスタにキー情報を取り込む
— CX = チェックする総数
一見すると、 CMP 命令でジャンプさせて いた 時より複雑になっているよう
ですが、チェックするキーの内容やジャンプ先が一目でわかるので、デバッグ
時などプログラムの内容を簡単に把握することができます。 また、 同じような
ルーチンが多い場合は、 「 CCJMP 」 以下を共通ルーチンとして使うことができ、
最終的には使用メモリ数も少なくなってくるでしょう。
このようなテクニックはゲームではあまり使うことはありませんが、各種の
ツール や実用 ソフ トにおいては結構有益なテクニックです。 SCAS 命令の活用
CDATA
DB
, ADFK ,
CTABL
DW
CCDTA , CCDTD , CCDTF , CCDTK
STD
CLOOP :
CALL
KSCAN
MOV
Dl,OFFSET CTABL +3
MOV
CX ,4
REPNZ
SCASB
JNZ
CLOOP
CCJMP :
SHL
CXJ
MOV
Dl,OFFSET CTABL
ADD
DI,CX
JMP
[ Dl ]
(注) DS = ES = CS と仮定する
146
法として覚えておくと便利です。
プログラムにバグはつきものですから、結局はそれを速やかにリカバーでき
るようなプログラムがいいプログラムといえるわけです。
147
閩
60
ベスト 5 のチェック
+4 -おこし……といっても、雷おこしの親戚じゃありません。過疎化に悩む地域を活性化
^ J し、新しいエネルギーを発生させようという、すばらしい企画のことです。
今でこそ全国どこにでも見られる現象ですが、元祖はここ大分県の一村一品運動なのです。ど
んなことでも、最初に考えて実行するというのは大変なこと。マシン語のテクニックも同じで
すね。
そうとわかっていても、マシン語でオリジナルのテクニックを考えるなんて、まだまだ先の話
です。とりあえず、現在のテクニックを覚えなければ . 。ゲームセンターで、よく スコアの
ベスト5を表示しているのがありますが、あれはどうやるんでしょう。
例えば、次のようにベスト5があるとします。そして、プレイした人の点数が BX レジスタに
ある場合、その人の成績が何番目であるか、ベスト5に入るならばベスト5の中に点数を組み
入れるようにしたいのです。
SC 0 R 1
DW
10000
SC 0 R 2
DW
8000
SC 0 R 3
DW
6000
SC 0 R 4
DW
4000
SC 0 R 5
DW
2000
わが村をマシン語村とするため、どうぞよろしく。
村長連合(大分)
■答- .
他人のプログラムを評価するのが趣味のような人がいますが、そういう人に
限ってオリジナルのテクニックは考えないものです。どんなにつまらないこと
でも、最初に考えるのはとても大変です。ましてや、それがブームになるとい
うことは、アイデア以上にその先見の明に感心してしまいます。
ゲームセンターで自分のスコアがベスト5に入るのは、名誉の表彰であり、
また次にプレイするための刺激剤でもあるわけですが、これも最初に考えた人
がどこかにいるはずです。ブームを越えて当然のように処理されているテク
ニック、これこそが究極のアイデアかもしれません。
148
この方法は色々あるでしょうが、結局は現在のベスト5と1つひとつ比較し
ていくことになります。次のプログラムは、 BX レジスタに現在のスコアを入れ
て コールす ると、ベスト5に入っていればそれを 登録し、 AX レジスタに順位
(6 位以下はすべて 6) を入れて返すというものです。なお、ベスト5に同じ
スコアがあった場合は、新しいほうのスコアを上位に入れます。
SCORE
PROC
MOV
SI , OFFSET SC 0 R 1
MOV
AX ,1
MOV
CX ,5
SCORL :
CALL
CPSCO
LOOPNZ
RET
SCORL
SCORE
ENDP
CPSCO
PROC
MOV
DX ,[ SI ]
SUB
BX,DX
JB
CPSCl
ADD
BX,DX
PUSH
BX
CPSCL :
MOV
[ SI],BX
XCHG
DX,BX
ADD
SI , 2
MOV
DX ,[ SI ]
LOOP
CPSCL
POP
BX
XOR
DX.DX
JMP
CPSRT
CPSCl :
ADD
BX,DX
ADD
S .,2
INC
AX
CPSRT :
RET
CPSCO
ENDP
— SC 0 R 1 から2バイト単位でベスト5が
登録されている
—初期順位
—登録スコア数
—新しい ベス ト X を 登録し、以前の ベス ト
X 以下の データを 繰り下げる
―ゼロフラグのセツト
(注) DS = CS と仮定する
では、ぜひマシン語で村おこしをお願いします。
149
± ろは徳川家の流れを祖母の父方の従兄弟(いとこ)の嫁の母の母方の父の祖父の兄の嫁
^ の父の母方の叔父の叔母にもつという、由緒ある身分の生まれ……。
まろは高貴な育ちゆえ、幼少のころはバアヤが毒味をしたあとでなければ食事を許されてい
なかったのであるぞよ。おかげで、いまだに熱いものはダメ。まれにみる猫舌にてあるぞ。と
ころが、なんとラーメンが好きで好きでたまらないのよ。
さますとメンはノビる。さまさなければ熱い。このジレンマをなんとか解消したいのである
が、なにか妙手の心得はないかな……。
それはさておき、まろの職業は寺小屋(早い話が塾)の講師にあるぞ。まろは、そこにおいて
家庭用電動頭脳(早い話がパソコン)を教えておるが、本当はよくわからんのであるよ。
先日も、子供たちに「マシン語でこの前のテスト結果を成績順に並べてヨ」と言われてしもう
たが、難しいのでその日の講義はおひらきにした。100点満点のテストを55人に実施した場
合、バラバラになっている点数を成績順に並べるには、どんな方法でやるといいのかのう。
なお、子供たちの点数はメモリの 「 TENSU 」 からに入っており、1人1バイトを使用してお
る。まろの悩みを聞いてくれることを期待しておるぞよ。
徳ノ川秀麿(島根)
■答-_
まず、猫舌のまろが苦心の末考えた秘伝のラーメンをお教えしましょう。そ
の名は‘氷ラーメン,……。できたてのラーメンに冷蔵庫の氷を4〜5個入れるだ
けで 0 K です。真夏でも汗をかかずに、熱いラーメンを涼しく短時間で食べら
れるので、食後の満足感に壮快感も加わって、もう病みつきになること間違い
なしです。ぜひお試しください。
満腹になったところで、数値ソートへと移りましょう。数値ソートとは、バ
ラバラになっている数値を大きい順あるいは小さい順に並べ換えるものです。
色々な方法が考えられますが、ここに紹介するのは小さい数値から順にフイッ
クスしていくものです。
プログラムの内容は、隣の数値と比較して小さければ入れ換えるという作業
を DX 回繰り返すことにより、その中の最小値をまず求めます。次に、残され
た中から最小値を同じようにして求めます。これを DX 回繰り返すことで、小
15〇
SORTS
PROC
MOV
DX ,55-1
CLD
SOTLO :
MOV
SI,OFFSET TENSU + 1
MOV
Dl,OFFSET TENSU
MOV
CX,DX
S 0 TL 1 :
CMPSB
JNB
S 0 TS 1
MOV
AL ,[ DI ]
XCHG
[ DH],AL
MOV
[ DI],AL
S 0 TS 1 :
LOOP
S 0 TL 1
DEC
DX
JNE
SOTLO
RET
SORTS
ENDP
TENSU
DB
XX,XX,.
—DX= 人数一 1
—隣の数値と比較し、小さければ入れ
換える
—55 人分の点数が連続
(注) DS=ES=CS と仮定する
さい数値からメモリに固定されてソートが完了するわけです。
1バイトのソートは、色々なソートの基礎となるものですから、プログラム
そのものよりもアルゴリズムを把握することが大切です。よくわからない場合
は、紙切れに1〜9までの数字を書き、バラバラにしてからソートするルール
を考えながら並べ換えてみるといいでしょう。
最後に、全国のラーメン屋さんへ、全日本猫舌の会よりお願いです。メニュー
に‘氷ラーメン’を入れてください。
/ 5 /
|E
62
E 八イト数値ソート
めてお便りを差し上げますが、私は田舎の中学校で教師をしている者です。昔は田舎の
中学校といえば、オンポロ校舎に少ない生徒数というのが相場でしたが、最近は東京の
地価高騰のあおりを受けて、都会風のハイカラな校舎に多数の生徒が通っています。
ただ、私のほうがオンポロ校舎タイプの教師なので、本当はこんな堅苦しい言葉が大の苦手で
す。でも、「……だっぺ」とか r ……べエ」と言おうものなら、テレビの影響で標準語^:した
生徒に笑われてしまいます。実に、ツライ職業……。
そこで、せめて中身だけでも時代の先端を行くようにと、成績管理にパソコンを導入しまし
た。プログラムにも、少しずつですがマシン語を取り入れています。とりあえずの処理として、
テストの合計点数を成績順に並べたいのですが、2バイトのソートはレジスタをどのように
ヤリクリしていいかわかりません。
次のように 「 TENSU 」 から100人分の点数が2バイトずつ並んでいる場合、どのようにして
プログラム化したらいいでしょうか。
TENSU DW
358
DW
125
DW
532
—100人分の点数が連続している
ア ー 、標準語がツライ。どうやったらイイんだっぺ。
田舎教師(茨城)
■答-_
ォッ、懐かしいベーべ一言葉。やはり、栃城(栃木と茨城)地方は、これが
出てこなくちゃダメだっペナ。伝統の言葉を滅ぼそうとしているのは、やっぱ
りテレビの影響と東京の地価高騰だべ……。でも、例の語尾上がりのアクセン
卜はまだ健在だっぺ。
それにしても、マシン語がいまだに機種によってバラバラなのは、なんと時
代に逆行した現象なのでしょう。もしかすると、コンピュータの開発者と いう
のは テレビを見て いる ヒマなどない のか もしれません。
とりあえず、本書は8086地方の方言ですべてを表現しなければなりません。
J52
さっそく質問にある2バイトのソートを行うことにしましよう。
SORTS
PROC
MOV
DX ,100-1
CLD
SOTLO :
MOV
SI,OFFSET TENSU + 2
MOV
Dl,OFFSET TENSU
MOV
CX,DX
S 0 TL 1 :
CMPSW
JNB
SOTS 1
MOV
AX ,[ DI ]
XCHG
AX , [ DM ]
MOV
[ DI],AX
S 0 TS 1 :
LOOP
SOTL 1
DEC
DX
JNZ
SOTLO
RET
SORTS
ENDP
— DX = 卜ータル人数一1
(注 ) DS = ES = CS と仮定する
基本的なアルゴリズムは1バイトのソート(問 61) と同じなので、今回はプ
ログラムがどのように変化したかを比べてください。
153
ブロック単位の文字サーチ
ビ
ンポー、ビンボー、涙のビンボー。
1 — この次は、どこの家にしようかな……。住みついて楽しいのは、モノスゴイお金持ちが
坂道をコロげ落ちるように貧乏になった時だけど、いくら働いても貧乏という家も住み心地
はいいもんだぜ。
だけどよ、お金っていうのは決してなくならないからな。ある所からお金が出れば、どこかに
そのお金は入っていく。全員貧乏という理想郷は、実現できそうでなかなか難しいもんだわ
さ。そう考えると、あっしらの存在価値なんて、本当はあるのかないのかわからないんだよ
ナァ〇
それに最近は中流意識の強い家が多いから、どこへ住みついても大した感激はないもんだぜ。
つまんないから、これからはコンピュータで適当な名前を作って、その名前があればそこに住
みつくようにしようと思うんだ。
あっしらの専用ファイルに、8文字単位でインプットされた名字ファイルというのがあるん
だ。たとえば、貧田さんという名字の家がある場合、そのファイルにはアスキーコードで f ヒ
ンタ • _ J しはスペースを意味する)と入っているんだ。
このファイルを DATA 1: NAME 1 へロードして (1000 H バイト分)、適当に作った名前があるか
どうかをサーチしようというわけだ。内容は、そのサーチ•ルーチンをコールしたら、 DI レジ
スタで名字の先頭アドレスを、そしてキャリーフラグで名字があったかどうかを返すような
もんがいいな。
おっと、そこから先のあっしの行動はまだ秘密だ。これは、いわゆる企業秘密ってやつだ。親
切に教えないと次はおまえの家に住むからな。
貧乏神(貧民峡谷)
あれ……??わが家にはすでに貧乏神が住みついていますよ。ワケもなく新
しい貧乏神が来ると、古い貧乏神とケンカになりますぞ。なにしろ、うちの貧
乏神様は先祖伝来の大物ですから……。
さて、これは文字列サーチの基本形となるプログラムですから、目的は別に
してグッドな質問といえるでしょう。
プログラムの使い方は、 「 SDATA 」 の部分にサーチしたい名字を入れ
「 SERCH 」 をコールすれば OK です。
154
—名字 (8 文字)
—サーチ • オフセツト•アドレス
—サーチ.セグメント•アドレス
—サーチ名字総数 (1000 h /8)
—次の サーチ アドレスにする
―名字のある先頭アドレスにする
—名字があつたことを示すフラグ
プログラムを実行すると、サーチしたい名字があればキャリーフラグを立て、
DI レジスタを その名字の先頭ア ドレスに してもどります。
その後の処理は……、もうおまかせするしかありません。でも、うちに来て
も餓死するだけですよ、きっと。
SDATA
DB
,ヒンタ , ,
SERCH
PROC
MOV
DI,OFFSET NAME 1
MOV
AX , DATA 1
MOV
ES,AX
MOV
AX,CS
MOV
DS,AX
CLD
MOV
DX ,200 H
SCHLP :
MOV
CX ,8
MOV
SI , OFFSET SDATA
CHK 8 L :
REPZ
CMPSB
JZ
SCHOK
ADD
Dl'CX
DEC
DX
JNE
SCHLP
JMP
SCHRT
SCHOK :
SUB
Dl ,8
STC
SCHRT :
RET
SERCH
ENDP
^55
|E
64
廛続テし夕からの文字列サーチ
Jy , んみょうなみあむなむあみばてれんめんまちゃあしゅうねぎとろこんぶなむなむかみ
^さまほとけさまあ一めんそ一めんほうれんそうきつねにたぬきにてんたまおとしがま
ちゃんちゃがまがまがいものしんしゅんさんそんしゃんそんしょう……。
非常に読みにくいものを紹介しました。これは私が栄えある初代教祖となっている‘ましむご
教’の経典の頭の部分です。お経はこのような感じで9801文字からできており、信者は毎朝これ
を祈らなければなりません。
ところが、信者のみならずこの教祖である拙僧も、このお経をまだ全部は暗記できていないの
です。なにしろ、深い意味がなさそうでありそうで、やっぱりないのがこの経典の特徴ですか
ら、覚えるのは簡単ではありません。しかし、結果的にはこれも信仰心を高めることに役立っ
ているのです。
というのは、‘ましむご教’にはできるだけ速くお教を唱えた者が高い位につくという厳しい戒
律があるからです。もちろん、教祖とて油断はできません。そのため、拙僧はこの大経典をコ
ンピュータに入力し、毎日少しでも先まで覚えようとしています。そこで必要なのが、文字列
のサーチです。
経典という長い文字列の中から、特定の文字列をサーチするにはどうするべきか。それができ
ないようでは、教祖としての威厳もあったものではありません。なお、サーチする文字列の長
さは不定ですが、最大で10文字程度です。
では、なむなむなむ……。
ましむご大僧正(魔心寺)
■答--
一度でいいから、なってみたいのが教祖さま。どんなにインチキくさい教祖
でも、そこに信者がいるのが不思議です。どれほどのご加護があるのかわかり
ませんが、ましむご教も信者がいるから成立しているのでしょう。
それにしても、このお経と戒律。なんとまァ、ありがたさを感じさせない世
紀末的ないい加減さ……。思わず入信したくなります……なんていう人がいる
んでしょうか。
とにかく、ここは入信したつもりで希望通りのプログラムを組むことにしま
しょう。実行方法は 「SDVAL」 に文字列の文字数 (2 1) を入れ 、 rSDATAJ
に サーチしたい 文字列を入れて 「SERCH」 を コールし ます。
ゆ
—文字数
—文字列
—お経のある先頭アドレス
—お経の総文字数
— CXS 文字列数一1の確認
実行後、サーチしたい文字列が見つかれば、キャリーフラグを立ててもどり
ます。 DI レジスタは、その文字列のあった先頭アドレスを示しています。この
プログラムではサーチできる最大文字列数は10ですが、 「SDATA」 のワークエ
リアを多くすればいくらでも長い文字列のサーチが可能です。
SDVAL
DB
6
SDATA
DB
’ ナムナムタ '
SERCH
PROC
MOV
DI,OFFSET OKYOU
MOV
AX,DATA1
MOV
ES,AX
MOV
AX,CS
MOV
DS,AX
XOR
AX, AX
CLD
MOV
CX,9801
SCHLP :
MOV
SI,OFFSET SDATA
MOV
AL,[SI]
REPNZ
SCASB
CLC
JNZ
SCHRT
MOV
AL,SDVAL
DEC
AL
JE
SCHOK
CMP
AX XX
JNB
SCHRT
PUSH
DI
PUSH
CX
MOV
CX,AX
INC
SI
REPZ
CMPSB
POP
CX
POP
DI
JNZ
SCHLP
SCHOK :
DEC
DI
STC
SCHRT :
RET
SERCH
ENDP
157
なお、プログラムの細かな注意点として、サーチしたい最初の1文字目が見
つかった場合、サーチ文字列数が1文字でなければ、お経の残り文字数がサー
チする文字数分だけあるかどうかをまず確認しなければなりません。また、 2
文字目以降で一致しなかった場合には、次のサーチはその場所からでなく、本
プログラムのように2文字目を改めて1文字目としてサーチし直さなければな
りません。さもないと、サーチ文字列が重なるように含まれている場合(今回
の例では「ナムナムナムダ」のような場合)、サーチ洩れを起こすことになります。
これで、教祖の威厳は保てるでしょう。なむなむなむ……。
r
なんな
んまち中あ c > ゆ今 ia 备と
32か在なむな&かみさ
ま域とけさまあ—めん«
1めん) S 今 n んぞ勿备〇
ね^ fe ぬさ K - C 加 fe ま B
と t > がまち中 A ) ち中がま
がまが s もの〇加 t > ゆん
さん«ん£>中ん « A)t>l:
故
閩
65
ブロック単位の文字列ソート
明王トーマス•エジソン……この名を知らぬ者はおるまい。近代科学はすべてこのエジ
^ソンの発明があったからこそ生まれたのじや。エジソンがいなければ、いまだにコン
ピュータなどなかったであろう。
わしはエジソンを神と崇拝し、エジソンに次ぐ発明を目指している町の発明家だ。本名を江路
苫州(えじ•とます)という。もちろん、両親が付けてくれた本名だ。
町の者は、わしのことをエジソン、いや「えじさん」と呼んでおる。この響きが、わしにとっ
てはたまらない魅力なのじや。
さてさて、わしだってエジサンの名に恥じないだけの膨大な発明がある。これまでに発明した
名作数は199にものぼっておる。特許や実用新案になったものは、残念ながらまだない。それ
が、町の発明家の いいところじや。 ワハハ ハ 。
すべての発明には16文字以内の名がついておる。そこで、それらをコンピュータに登録してア
イウエオ順に並べたいのだが、マシン語は発明ほどには得意でないのだ。
どうやっていいのか教えてくれたら、わしの発明した「灰皿パイプ」をプレゼントしよう。こ
れは灰皿に長いチューブを付け、灰皿側のタバコをチューブでスパスパ吸うものじやよ。ワハ
ハノ、 . 〇
トマス • エジさん(富山)
■答- .
ワハハハ . と言われても、タバコを吸わない人にとっては少しも役に立た
ないプレゼントです。せっかくですが、プレゼントは辞退しておきましょう。
それより、発明の一覧表でも機会があったら見せてください。
ここに紹介するプログラムは、16文字ステップで文字列をソートするもので
す。原則的には同じ文字列がないことを前提としたプログラムですが、同じも
のがあってもソートに支障をきたすことはないでしょう。
発明の名前は、セグメント名 DATA1、 オフセット名 NAME から16文字ごと
に置いてあるものとします。したがって、たとえば「灰皿パイプ」であれば、
[ハイサ•ラハ。イフ。_」しはスペースを意味する)のようにトータルで 16 文
字になるように登録するということです。
ソートのアルゴリズムは、問61や問62の数値ソートと同じです。アスキーコー
ドも結局は1バイトの数値ですから、16桁の十六進数を数#:ソートしたもの
159
MSORT
PROC
MOV
DXJ 99
MOV
AX . DATA 1
MOV
DS,AX
MOV
ES,AX
CLD
JMP
S 0 TL 3
SOTLP :
MOV
SLOFFSET NAME
MOV
Dl,OFFSET NAME + 16
MOV
CX,DX
S 0 TL 1 :
PUSH
CX
PUSH
Dl
PUSH
SI
PUSH
SI
PUSH
Dl
REPZ
CMPSB
POP
Dl
POP
SI
JNB
NOEXS
MOV
CX ,8
EXSOT :
MOV
AX ,[ DI ]
XCHG
AX , [ SI ]
MOV
[ DI],AX
ADD
SI ,2
ADD
Dl ,2
LOOP
EXSOT
NOEXS :
POP
Dl
POP
SI
POP
CX
ADD
Dl ,16*2
LOOP
SOTL 1
S 0 TL 3 :
DEC
DX
JNE
SOTLP
RET
MSORT
ENDP
―登録してある名前の総数
―データ.エリアのセグメント値
―名前のある先頭アドレス
—2 番目の名前のあるアドレス
と考えることもできるわけです。
発明というと、つい特許大発明—大金持ちという発想をしてしまいますが、
日本のェジさんはどうなんでしようか。気になるところです……。
i6o
シフト J 旧コ-ドから J 旧コードへ
『ノ、日は東に明日は西……コピー求めて右往左往』
I "7 ここでい うコピーとは、宣伝文句という意味の コ ピーです。複写のほうの コ ピーではな
いので勘違いしないでください。冒頭のコピーは、そんなコピーライターの実体を文字で表現
したものです。もちろん私のオリジナルコピーです。
カタカナ職業の花形ともいえるコピーライタ-ですが、ハデな外見とは裏腹にハードな仕事
です。文学的なセンスや広告の知識が要求されるだけでなく、落雷のようなひらめきが必要な
のです。
そんなわけで、私はオンポロのキャンピングカーで‘ひらめき’を求めて日本国中をさまよって
います。ただいま熊本あたりをさまよい中です。
そこで、気になるのが マシン 語による漢字の取り扱いです。今、 シフ ト JIS コードを JIS コー
ドへ変換したいのですが、どのようにプログラムを組んでいいものか、さっぱりひらめかない
のです。なんとかならないものでしょうか。
ピーコ ー物語(熊本)
■答- -
マシン語も‘ひらめき,が勝負です。‘ひらめき’とは稲妻……これが落雷するか
カラ光に終わるかは、プログラミング技術にかかっています。とはいえ、技術
の前にアルゴリズムの壁を崩さないことには光ることもできません。このあた
りのバランスは、 コピー ライ ターに 通じるものがあるのかもしれません。
シフト JIS とは、 JIS コードをシフトして変換し定義されるコードのことで
す。シフト JIS コードから JIS コードへ変換するには、次の手順が必要です。
① シフト JIS コードの第1バイト S 9 F h ならば、第1バイトから 71 H を引く
② シフト JIS コードの第1バイト >9 F h ならば、第1バイトから B 1 H を引く
③ シフト JIS コードの第1バイトを2倍して1を加える
④ シフト JIS コードの第2バイト >7 F H ならば、第2バイトから1を引く
⑤ シフト JIS コードの第2バイト 29 E H ならば、第2バイトから 7 D H を引き、第
1バイトに1を加える
⑥ シフト JIS コードの第2バイト <9 E H ならば、第2バイトから 1 F H を引く
i6i
このシフト JIS コードから JIS コードへの変換を、具体的にプログラムにす
ると次のようになります。
SHTOJS
PROC
CMP
AH,0A0H
JNB
STJOO
SUB
AH,071H
JMP
STJ01
STJOO :
SUB
AH,B1H
STJ01 :
SHL
AHJ
INC
AH
CMP
AL,80H
JB
STJ02
DEC
AL
STJ02 :
CMP
AL,9EH
JNB
STJ03
SUB
ALJFH
JMP
STJRT
STJ03 :
SUB
AL,7DH
INC
AH
STJRT :
RET
SHTOJS
ENDP
このプロシージャは、シフ ト JIS コードが正常であることが前提ですが、も
し エラー コード入力の可能性がある場合には、 プロシージャを コールす る前に、
エラー • チェ ック をしなければなりません。
おまけとして、 JIS コードからシフト JIS コードへの変換手順も參考のため
に書き添えておきます。
① JIS コードの第1バイトが偶数なら第2バイトに 7 D H を加算し、奇数ならば第
2バイトに 1 F H を加算する
② 第2バイトが 7 F H 以上なら、第2バイトを+1する
③ 第1バイトから 21 H を引き、それを2で割る
④ 第1バイトに 81 H を加える
⑤ 第1バイトが 9 F H より大きければ第1バイトに 40 H を加算する
これで、きっと激しいヒラメキが生まれることでしょう。
162
67
ァスキ-コ-ドのかけ算(鼷タィプ)
r _ ■の石がいいね」と君が言ったから8月6日はハチロク記念日
I 一「32ビットになれよ」だなんて16ビット2個で言ってしまっていいの
キャリーというフラグをキープすることの期限が切れてポップフラグ
ハチロクでいいのというユーザーがいて言ってくれるじやないのと思う
「 AX にムーブしろよ」「ジャンプしろ」といつもいつも命令形でプログラムする君
わたしはマシン語を自在に使い、流れるようにプログラムする女流歌人です。自己紹介の代わ
りに、わたしの短歌作品群の中で特に気に入っているものを選んでみました。誰でもできる
……と思っていただけるところに、この作品のよさがあります。
どこかで見たような短歌だと思う人もいるでしょう。実は' わたしもそう思っているのです。
だから、オリジナルな短歌を目指して、マシン語プログラムのアイデアに磨きをかけていま
す0
例えば 、 DATAAXDATAB = DATAC というかけ算を、アスキーコー•ドのままで計算できない
ものでしょうか。例えば、’23’ X ’45’を次のようにするやり方です。
3233…,23’の アスキーコード
X _ 3435… ’45’の アスキーコード
313135 - ,115,(23 X 5) の アスキーコード
3932 … ,92,(23 X 4) の アスキーコード
31303335…’1035’の アスキーコード
これができれば、プログラム効率はグンとよくなると思うのですが……。
マシン語歌人•俵まり(岡山)
■答- .
マシン語を口語体のように使いこなし、流れるように美しいプログラムを組
むというナゾの女流歌人。そんな歌人のマシン語短歌集『ハチロク記念日』が
300万部を超す売行きを示すという時代……になったらいいなと思うハチロク
記念日。
マシン語とはアルゴリズムの美を追求する言語です。二進数のかけ算から、
アスキー コードのかけ算 へと アルゴリズムを変えようとする点に、限られた文
字の世界で美を追求する歌人ならではの美意識を感じます。
では、このアルゴリズムにしたがってプログラムを組んでみます。
KETASU
EQU
2
DATAA
DB
33H,32H
DATAB
DB
35H,34H
DATAC
DW
KETASU DUP(O)
DATAW
DB
KETASU+ 1 DUP(O)
DATAN
DW
KETASU
AMULB
PROC
MOV
D し OFFSET DATAC
XOR
AX, AX
MOV
CX,DATAN
REP
STOSW
MOV
BP,OFFSET DATAC
MOV
BX,OFFSET DATAA
MOV
CX,DATAN
JCXZ
AMBRT
AMBL1 :
PUSH
CX
MOV
Dl,OFFSET DATAW
XOR
AX, AX
MOV
CX,DATAN
INC
CX
REP
STOSB
MOV
Dl,OFFSET DATAW
MOV
CX,DATAN
MOV
SI,OFFSET DATAB
MOV
DL,[BX]
AND
DL,0FH
CALL
MULTB
CALL
ADDTB
INC
BX
POP
CX
LOOP
AMBL1
MOV
CX,DATAN
SHL
CXJ
MOV
AL,30H
MOV
Dl,OFFSET DATAC
AMBL2 :
OR
[DI],AL
—演算の桁数(任意)
—計算結果格納用
—ワークエリア
—加算用ポインター初期値セット
—最大桁数(任意)
—最大桁数= 0なら終了とする
—ワークエリアの初期化
— DATABXDATAA 1 桁
—演算結果をワークエリアへ加算
164
INC
Dl
し 0 OP
AMBL2
AMBRT :
RET
AMULB
ENDP
MULTB
PROC
PUSH
Dl
MULTL :
MOV
A し [SI]
AND
AL,0FH
MUL
DL
AAM
ADD
AUDI]
AAA
MOV
[DI],AX
INC
Dl
INC
SI
LOOP
MULTL
POP
Dl
RET
MULTB
ENDP
ADDTB
PROC
PUSH
BP
CLC
MOV
CX,DATAN
INC
CX
ADDTL :
MOV
AL,[DI]
ADC
AL,DS:[BP]
AAA
MOV
DS:[BP],AL
INC
Dl
INC
BP
LOOP
ADDTL
POP
BP
INC
BP
RET
ADDTB
ENDP
—DATAA の 1 桁と DATAB とのかけ算を実行
—かけ算の結果を DATAC へ加算
—加算用ポインター (DATAC ) の保存
—かけ算の桁数+1
—加算用ポインターを1桁ずらす
(演算結果の10倍に相当する)
(注) DS = ES=CS と仮定する
このプログラムは任意の桁(この例では2桁)を持つアスキーコード間のか
165
け算の例ですが、基本的なアルゴリズムは、筆算のプロセスをそのまま置き換
えたものです。このブログラムで注意しなければばらないのは、 DATAA の数
値と DATAB の数値の桁数が合わない時に、頭に0を付けなければならないと
いうことです。まあ、字余りは0で埋めるというわけですから、短歌よりもずっ
と楽かもしれませんね。
166
_
卜のかけ算(韓タィ:〇
Z —、オホン!!
小生はバグというケチな虫でやんす。ご存じのように、小生は姿は見えねど自然発生的
に生まれ、適当に暴れ回ったあとは強制的に抹消される運命でやんす。考えると、わびしい運
命でやんすネェ。
その代わり、小生には駆除剤とかワクチンのような特効薬は存在しないので、プログラムさえ
あればいつでも生まれる可能性を持っているんでやんす。神様は、ちゃんと小生みたいな虫け
らにも生きる道を与えてくれたんでやんすネ。
ところで、かけ算とは2バイト X 2バイトとは限らないすね。4パイト X 4バイトのかけ算
だって当然必要でやんすから。こんな場合は、どうやったらいいんでやんしょ。
足し算の ループで やればいい……なんていう回答なら不要でやんすからね。速度とか美しさ
なんて小生はどうでもいいんでやんすが、小生の生まれる可能性が少ないプログラムは見て
もつまんないんでやんすよ!!
ばぐちやん(メモリの森)
■答-《
プログラムのないところにバグは発生しませんが、バグもまた生きるために
プログラムを選んでいたとは気付きませんでした。眠たかったり疲れていたり
すると、知らず知らずのうちにバグに狙われているのかもしれません。
では、 ANSW 1 = DATAAXDATAB をプログラムしてみます。なお、
DATAA 、 DATAB にはあらかじめ4バイトにわたって、数値が格納されてい
るものとします。
DATAA
DD
0
DATAB
DD
0
ANSW1
DQ
0
DW
0
MULAB
PROC
MOV
BX,OFFSET ANSW1
MOV
DI,BX
MOV
CX,5
—計算用ダミーエリア
/67
XOR
AX , AX
CLD
REP
STOSW
MOV
S し OFFSET DATAA
MOV
Dl,OFFSET DATAB
CALL
MLBAS
ADD
Dl ,2
ADD
BX ,2
CALL
MLBAS
MOV
D し OFFSET DATAB
ADD
SI ,2
CALL
MLBAS
ADD
BX ,2
ADD
Dl ,2
CALL
MLBAS
RET
MULAB
ENDP
MLBAS
PROC
MOV
AX ,[ SI ]
MUL
WORD PTR [ Dl ]
ADD
[ BX],AX
ADC
[ BX +2 ],DX
ADC
WORD PTR [BX + 4],0
RET
MLBAS
ENDP
— ANSW 1 + ダミーの初期化
(注) DS = ES = CS と仮定する
この プログラムで注意することは、計算結果を格納するエリア ANSW 1 に10
バイト確保するということです。また、数値は符号無し(プラスのみ)として
います。
これを応用すれば任意の桁数のかけ算が可能になりますが、計算結果の桁数
に、2バイトのダミーを加えることを忘れないでください。
168
琶
69
AXtCX=BX 七捨 m )
I . の都ベネチア……。いったい水の都とはどういう意味なんでしよう。水がおいしいの
フか、それとも川が多いのか、それとも島がたくさん浮かんでいるのか……。不思議な魅
力に憧れて、ここベネチアへやって来ました。
まるで海の上に敷かれたような鉄道がベネチアへの入口です。列車の窓から見えるものは、右
も左も広大な海原ばかり、いやがおうにも水の都への期待が高まります。やがて列車はサンタ
ルチア駅へ到着です……。
駅前には広場があり歩道もあります。その向こう側には 「 TAXIJ のマークが……。ところが、
なんとこれが船なのです。タクシーが船ならバスも船。つまり、車道はすべて船道というわけ
です。
路地裏には歩道がなくても船道はあります。歩いていけない場所へも、船なら行けるのです。
まさに水の都……。
そういえば、日本を出る時にマシン語で AX + CX = BX (レジスタです)のプログラムをやり
かけたままでした。気になるので、やっておいてください。ついでに、小数第1位で四捨五入
するようなプログラムもお願いします。なお、数値はすべて正の数です。
旅情の人(ベネチア)
■答- •
ベネチアは潮の香りでいっぱいです。百を超える島々が運河の道路を創り、
運河は家と家を結び町を創ります。水の都というより水上者 [5 市という感じです。
そんなところを旅している旅情の人……。実にうらやましい限りです。
さっそく、気になる AX + CX 二 BX をプログラム化してみましょう。一般に、
割り算は DIV 、 IDIV を使いますが、この場合には符号を考えませんから 、 DIV
を使います。当然、 CX 本0でなければなりません。
WARIS : CWD
DIV
CX
MOV
BX , AX
このプログラムでは、先頭で cx = o のチェックをしていませんから、 CX 本 0
が前提となっています。もし、0で割った場合には、除算エラーの割り込みを
ibg
生じ、強制的に割り込みルーチンヘと処理が移動しますから注意してください。
また、演算の結果は、商が AX レジスタに、余りが DX レジスタへと格納され
ます。
質問にあった、小数第1位で四捨五入(十六進数なので正しくは七捨八入と
なる)するには、この余り ( DX レジスタ)が割る数 ( CX レジスタ)の半分以
上であれば、 BX レジスタを+1することで可能となります。注意したいのは、
CX レジスタを半分にして余りが出る場合は切り上げるということです(例え
ば、7なら4とする)。
— CX = CX +2
—七捨八入を実行
「 SHRCX ,1」 による1/2では切り捨て (7 なら 3) となりますが、その時の
キヤリーフラグを含めて減算することで、結果的に切り上げた値を減算してい
ます。
これで、安心して旅が続けられることでしょう。
WARIS
PROC
XOR
DX.DX
DIV
CX
MOV
BX , AX
WAEND :
SHR
CX # 1
SBB
DX,CX
CMC
ADC
BX ,0
WARET :
RET
WARIS
ENDP
no
閩
70
アス: K 1- ド痛り算_,賴)
_ ンニンニン . !!
一拙者は伊賀の忍者。山を越え、野を越え、時代を越えて、現代社会へやって来たのでご
ざる。得意の忍法は「排気ガス隠れ」……排気ガスに少し細工をして、煙玉で消えたようにす
るのでござる。
昔の忍者は修行に修行を重ね、必死になって独自の忍法を開発したのでござるが、すでに伊賀
には『伊賀忍法トラの巻』があるでござる。それを見れば、こんな忍法なんて簡単なのでござ
るよ。
そんなことより、今は甲賀忍者のコンピュータに忍び込むほうが大変なのでござる。なにし
ろ、忍者のコンピュータというのはカラクリだらけ、まるで忍者屋敷のようなワナが待ってい
るのでござる。
下手にプログラムを送ろうものなら、アツという間にやられてしまう。まずは敵の情報を分析
しなければならぬでござる。そのためには、アスキーコードで表された数値の割り算ができな
ければならない。それができないところに拙者の悩みがあるのでござる。
なんとか甲賀に内緒で教えてくれぬでござらぬか……。
影丸(三重)
■答- .
伊賀の影丸……!?懐かしい名前でござる。拙者は大の影丸ファンでござる
ゆえ、サインがほしいのでござるが……。
さて、数値アスキーコードの割り算ですが、幸い、8086には割り算用のアス
キー補正命令がありますから、これを利用することになります。プログラムは、
小数点以下切り捨ての場合と小数第1位で七捨八入した場合とに分けてありま
す。どちらも AX + BL 二 CL という計算ですが、当然 BL 本0でなければなりま
せん。
/ 7 /
小数点以下切り捨て
WARIA
PROC
AND
AX ,0 F 0 FH
AAD
AND
BL ,0 FH
JE
WRIART
DIV
B し
MOV
CL,AL
WRIART :
RET
WARIA
ENDP
小数第1位七捨八入
WARIA
PROC
AND
AX ,0 F 0 FH
AAD
AND
BL ,0 FH
JE
WRIART
DIV
B し
SHR
BL ,1
SBB
AH,BL
CMC
ADC
AL ,0
MOV
CL'AL
WRIART :
RET
WARIA
ENDP
問 69 を読まれた方には、簡単でござったであろう ……ニンニン。
^^ Dbx ^ cx = bx.al ('雇三位疆)
- の伊賀者メ……!!甲賀のコンピュータに無法侵入しようなんて、まだまだ考えが甘
w い甘い。拙者とておぬしの作るプログラムくらい見当はつくわ。
甲賀にも『甲賀忍法トラの巻』はあるし、伊賀のコンピュータに送り込む刺客プログラムも近
いうちに完成するだろう。しかし、伊賀の忍者屋敷もなかなか手ごわいな。先日送った偵察プ
ログラムは、とうとう戻ってこなかった。どうやら、敵のチェックプログラムに破れたようだ
.^iv/E'o
そこで、拙者は伊賀の計算基準を超すような、正確な割り算プログラムで対抗しようと思うの
だ。つまり、16ビットの割り算を小数第2位まで求めようというのだ。レジスタ構成としては、
次のようなものを考えている。
BX + CX = BX.AL
これまでは、商は整数だったから誤差がどうしても大きくなる。計算結果を CX 倍しても元の
BX とは相当違った値になる可能性を否定できなかった。これが小数第2位までになると、ほ
ぼ正確に元の値に戻すことができるのだ。
(例)四捨五入による計算
50+30=2 — 2 X 30=60 . 誤差が大きい
50+30 = 1.67 -> 1.67 X 30=50.1. 誤差が小さい
これをなんとか実用化したい。伊賀に内緒で頼む。
サスケ(滋賀)
■答-《
少年忍者サスケ……。拙者はサスケのファンでござる。ここに登場したサス
ケ氏はかなり大人びていますが、それでもやはりサスケはサスケ。ぜひサイン
をください。—なんと節操のない人物!!
それにしても、コンピュータをいじる影丸とサスケ……いったい現代の伊賀
と甲賀の忍者は何を考えているのでしょうか。割り算がターゲットになる理由
もさっぱりわかりません。とにかく、質問通りにプログラムを組むことにしま
す。割る数 ( CX ) のゼロチェックはしていませんから、その恐れがある場合は
計算前にそのチェックをしてください。
173
WARIX
PROC
MOV
AX,BX
MOV
DX ,0
DIV
CX
MOV
KEPAX,AX
XOR
AX , AX
MOV
AH,DL
MOV
DL,DH
MOV
DH,AL
DIV
CX
MOV
BX,KEPAX
SHR
CXJ
SUB
DX,CX
CMC
ADC
AL ,0
ADC
BX ,0
RET
WARIX
ENDP
KEPCX
DW
0
— KEPAX に整数部の商を求める
—DX : AX に余リ X 100 H を求める
—小数第3位の七捨八入計算
(注) DS = CS と仮定する
整数部の商は簡単に求められますが、小数部はレジスタの役割とアルゴリズ
ムを理解しておかないとわかりにくいかもしれません。順を追って確認しま
しよう。整数部の計算が終わった時点で、レジスタの内容は次のようになって
います。
AX レジスタ=商(整数部)
DX レジスタ=割り算の余り
CX レジスタ=割る数
小数点以下の割り算は、余り部分を 100 H 倍して再び割り算をして求めていま
す。なお、ここで求められる小数部の商は十六進数ですから、分数でいうなら
1/256単位の数値となります。
最後に、小数第3位の七捨八入処理をします。七捨八入した結果によっては
174
AL レジスタが桁上がり ( FFh ^ OOh ) するかもしれませんので、その場合には
整数部 ( BX レジスタ)が+1されるよう配慮しなければなりません。
忍法同様、最後の最後まで気をゆるめないでください……。
175
BX . ALXBP = AX _ IH 2 七捨 M )
の昔、アラブの砂漠で 3 人の男が遺産相続でモメていた。亡くなった父親の遺言による
^ と「遺産のラクダは、長男が1/2、次男が1/4、三男が1/6、仲良く分けろ」とあったそ
うだ。ところが、ラクダは11頭しかいない……。
今にもなぐり合いが始まろうという時、一人の老人が現れ「お若いの、わしの持っているラク
ダを一頭やるからケンカはやめるがいい」とラクダをくれた。三人は喜んで、12頭のラクダを
遺言通りに分けた。
長男: 12 X 1/2= 6
次男: 12 X 1/4=3
三男: 12 X 1/6= 2
分けてみると一頭余っている。分配に満足した3人は、そのラクダを丁重に老人に返したそう
だ。老人は、ニヤリとしていずこかへ去っていったという。
……こんな話をしながら、父がポクたちに50000円ものお年玉をくれるというのだ。ただし、
長男が270/555、次男が180/555、三男が105/555となるように、マシン語を使って分配するよ
うにと命令された。
長男のポクとしては、なんとしてもこのプログラムを完成させなければならない。どうか、ァ
ラブの老人になってください。
総領の甚六(高知)
■答- .
アラブの老人になってと言われても、あれは合計が11/12だったからメデタシ
メデタシとなったわけで、ここで似たようなことをする気分になって505円を出
したとしても、結果は555で割り切れるようになるだけでお金は戻ってこない
それなら、プログラムを組むほうがマシというもの。すでに、問71によって
小数第2位までの割り算ができますから、それをベースに各人の金額を求めて
みることにしましょう。プログラムは、長男だけについて示しています。
割り算 (50000/555) の結果に、長男の分として270をかけるわけですが、か
け算の方法は単純に ( MUL ) 命令を使っていますが、小数点以下の処理が増え
"6
—BX + CX = BX.AL (問 71 を利用)
—BP = かける数
—DX : AX=AXXBP
卜 AX=DX : AX+CX
—最後の七捨八入
— AX=BX
—DX : AX=AXXBP
た分だけレジスタが不足します。そのため、ここでは BP レジスタを活用してい
ます。
最終的な計算結果は、小数第1位を七捨八入したものが AX レジスタに入り
ます。
MAN 01
PROC
MOV
BX , 50000
MOV
CX ,555
CALL
WARIX
CBW
MOV
BP ,270
MUL
BP
MOV
CX .100 H
DIV
CX
CMP
DX , 08 OH
JB
MAN 02
INC
AX
MAN 02:
MOV
CX.AX
MOV
AX,BX
MUL
BP
ADD
AX XX
RET
MAN 01
ENDP
«計算結果〉〉
長男: 24324 (AX : 5 F 04 h )
次男:16216 (AX : 3 F 58 h )
三男: 9459 (AX : 24 F 3„)
合計では 49999 円と割り切れなかった分の誤差が出ますが、小数点以下を考
慮しない計算に比べればはるかに高精度です。もしも残った1円でモメるよう
であれば、最後の七捨八入を五捨六入 (「CMP DX,80H」—rCMP DX,60
H」) とすれば、三男の取り分だけが +1 されて合計でビタリ50000円になりま
す 。
現代版 アラブの 老人…… 。それは、コンピュータという 砂漠に生きる マシン
語プログラムのことかもしれません。
177
73
アストコ-ドから BX レジスタへ変換
■暦2100年 . 。
^1900年代後半に出回っていた8086は、すでにその役目を完全に果たし、 CPU として成
すべき使命を全うしたかに思われていた。それどころか、その存在はコンピュータ史研究家の
間でも忘れられた存在となっていた。
なにしろ、子供向けパソコンでさえ1024ビット CPU を8個搭載している時代だ。立体テレビ
による完全3 D 画面が、まるでビデオ映像のようにパソコンで展開されている。しかも、それ
は家庭でのゲームである。ゲームセンターは亜空間体験ゲームルームとなり、プレイヤーは完
全に立体虚像化された空間を自由にさまよったり、勇者として悪を倒すという古典的シナリ
才の世界で実際に戦ったりできるのであった。
私は、ドラゴラン銀河系ツバイシュタイン星タイムトラベラーである。地球の未来を見てきた
ので、正直に報告しておこう。
……で、私のタイムマシンであるが、メイン CPU はなんとその8086なのである。ところが、
どうもプログラムにバグがあるらしいのだ。アスキーコードで入力された年代(画面上の数
字)を、マシン語プログラムで操作するために2バイトの数値に変換しなければならないのだ
が、それがうまくいっていないようだ。
ところが、残念ながら私は8086マシン語はよくわからない。未来の情報を教えた代わりに、
8086でのプログラムを教えてもらいたい。
アストロ •ベイダー (TWS 星)
■答--
テレビ画面の中で実際にプレイをする……これは、まさに究極のゲームとい
えるでしょう。もっとも、それが実現した時には、すでにそれ以上のゲーム欲
が人間を支配しているのは間違いないでしょうが . 。
平面型テレビの次は立体テレビとなると考えられていますが、いくら未来の
テレビでも実像テレビ(テレビの中の料理が食べられる)だけは無理でしょう
ね。となると、虚像空間の次は何が出てくるのか、そのあたりの情報も知りた
いものです。
未来はともかく、当面はアスキーコードで示された数字を2バイトの数値に
変換するという現実的なプログラムを完成させなければなりません。これは、
キースキャン結果がアスキーコードで返される場合や、テキスト画面上に表不
されている数字を数値に変換するという場合にも必要な基本テクニックです。
ADATA
DB
’ ’,’12345,,,,
ATOHL
PROC
MOV
Dl,OFFSET ADATA + 1
MOV
AL,’ ,
MOV
CX,0FFFFH
CLD
REP
SCASB
DEC
Dl
XOR
BX,BX
MOV
CX,1
CALL
AREAD
MOV
CX,10
CALL
AREAD
MOV
CX, 100
CALL
AREAD
MOV
CX, 1000
CALL
AREAD
MOV
CX, 10000
CALL
AREAD
RET
ATOHL
ENDP
AREAD
PROC
DEC
Dl
MOV
AL,[DI]
CMP
八し/’
JE
AREND
SUB
AL/O'-l
ARDLP:
DEC
AL
JE
ARRET
ADD
BX,CX
JMP
ARDLP
AREND:
POP
AX
ARRET:
RET
AREAD
ENDP
—データはスペースで囲まれている
— Dl = データの先頭アドレス
—Dl = データのエンドサイン (’ ’) アドレス
— BX = 十六進数に変換後の値
—アスキーコードを「数値+1」に変換
— SP 合わせのダミー
(注) DS = ES = CS と仮定する
H9
この プログラムでは、, ,(スペース) を データの 前後に存在させることで数
字の区切りとしていますが、これはケースバイケースで自由に変更することが
できます。また、変換できる最大数字数は5桁です。5桁以上の数字列の場合
は、後半の5桁が有効数字となります。
ただし、2バイト (0 〜 65535) を超えるかどうか、あるいはデータに数字以
外の文字があるかどうか等、異常事態のチェックはしていません。キースキャ
ン データの 場合であれば、少なくとも数字の上下 (’0’ 〜’9,)くらいはチェック
したほうがいいでしょう。
これでタイムマシンが直ったなら、西暦2200年あたりのコンピュータ事情も
調べてきてください。
i8o
74
アスキ-コードから BCD d 値へ変換
- ちらはツバイシュタイン星よりタイムマシンの製造依頼を受けたトライシュタイン星
w のトヨサン時動社です。実は当社のタイムマシンにバグが発見されたのですが、すでに
ツバイシュタイン星のタイムトラベラーは貴地球に向かってしまった後でした。
このままでは、時空間をフラフラする危険性があるので、ぜひ入力した年代をマシン語上で使
用できるように修正したいのです。
プログラムの内容は、アスキーコードで入力された年代を BCD による数値データに変換する
というものです。もし、間違って2バイトの数値などに変換してしまうようなことがあると、
ますます時空間の狂った世界へワープしてしまうでしょう。
ツバイシュタイン星の話では、乗務しているタイムトラベラーはマシン語が弱いとのことな
ので、おそらく地球にて誰かに質問するはずだということでした。きっとこの情報を受信でき
るような機関へ質問していると思われるので、そのような質問があったら次のように修正を
するように連絡してください。
では、プログラムを送りまままままままま一すすすす。やややややや、はははは発信機ががが
がが、ここここ故障ししししててててまま . 。
技術部長ノホホン (TRS 星)
■答-_
運の悪い時はすべてがスレ違いになってしまうもの。タイムマシンのバグ発
見が遅れたことで、運に見放されてしまったのかもしれません。ほんの少し前
に、ツバイシュタイン星のタイムトラベラーから2バイトの数 tt : に変換する質
問があったばかりです。
こうなったら、運が好転することを期待するしかないでしょう。もしかする
とまだ今の年代をうろついている可能性もないとはいえません。とにかく、ア
スキー コードの数字列を BCD に変換するプログラム、これを急いで作ること
にします。
ADATA
DB
’,/12345,
BCDDT
DB
0,0,0
ADBCD
PROC
—データはスペースで囲む
— BCD に変換された値が入る
i8i
ADBL 1 :
ADBRT :
ADBCD
PUSH
DS
PUSH
ES
MOV
AX,CS
MOV
DS.AX
MOV
ES,AX
MOV
Dl,OFFSET ADATA + 1
MOV
AL / ’
MOV
CLD
CX # 0 FFFFH
REPNZ
SCASB
DEC
Dl
MOV
BX,OFFSET BCDDT
MOV
CX ,3
XOR
AX , AX
XCHG
DI,BX
REP
STOSB
XCHG
DI,BX
DEC
BX
MOV
CH ,3
DEC
Dl
MOV
AL ,[ DI ]
CMP
AL / ,
JE
ADBRT
MOV
CL ,4
SHL
AL,CL
DEC
Dl
MOV
AH ,[ DI ]
MOV
CL ; 4
SHR
AX , CL
MOV
[ BX],AL
CMP
BYTE PTR [ Dl ],, ,
JE
ADBRT
DEC
BX
DEC
CH
JNE
ADBL 1
POP
ES
POP
RET
ENDP
DS
—Dl ニデータのエンドサイン (• ’) アドレス
—BX=BCD に変換された値が入るアドレス
※
—BCD データエリア•クリア
—※ ( BX=BCDDT+2 となつている)
182
BCD に変換された数値は 「 BCDDT 」 からに入ります。このブログラムでは
メモリを3バイトしか用意していませんが、メモリさえ確保すれば、 BCD によ
る数値は桁の制限がありません。桁を増やす場合は、 BCD のメモリ数を意味す
るレジスタの値(※印2箇所)も変更してください。
ここで、アスキーコードから BCD の数値に変換している処理に着目してみ
ましょう。アスキーコードの数字 (30 H 〜 39 H ) は下位4ビットが BCD に必要な
部分ですから、1バイトにつき2つのデータが必要になります。注意しなけれ
ばならないのは、数字列の総数が奇数の場合です。ここでは、ダミーとしてス
ペース (20 h ) で BCD 変換を終了させていますが、スペースの下位4ビットニ
0であることが、このダミー処理をうまく成立させているのです。
せっかく作ったプログラムですが、肝心の質問者は不明、連絡先も不明……。
事情はよくわかりませんが、バグだけは今も未来も変わらぬ存在のようです。
183
閩
75
BCD _をアスキ-:]-ドへ変換
イ、ちょっとそこのタイムマシン止まりなさい。ジグザグワープは銀河交通法で禁じら
/ れていますヨ……オイ、いつまでフラフラしたワープを繰り返すのだ。もしかして、
酔っているのか。酒酔いワープは即1年間の免停と罰金20万ゴールドだぞ!!
アツ、また不法なワープをした。どこへ行くか、コラ……『銀河タイムパトロール隊員の白い
タイムマシン』通称白タイの命令には絶対服従という法律を忘れたのか。この法律は、各星が
集まってできた銀河連邦の「時空ワープに関する交通法規特別準備委員会」によって正式決定
された由緒ある基本六法の1つだぞ!!
才、やっと止まった。なんだ、年代の アスキーコー ドを BCD に変換するプログラムを直して
いたのか。仕方ない、ジグザグワープの件は許そう。だが、ワープ先の年代はちゃんとタイム
マシンの前後に表示しなきゃダメじゃないか。
その方法……? それは BCD の数値をアスキーコードに変換して、指定のメモリに入れてや
ればいいのさ。ン、マシン語がわからない……!?そんなムズかしいこと、オレに聞かないで
くれよな。
だ、誰か……この会話を傍受していたらプログラムを組んでやってくれないか。そうしない
と、オレも見張りとしてここを動けない……トホホ。
銀河のシェリフ(地球出身)
■答--
どうやらアスキーコードを BCD に変換するというプログラム(問 74) は届い
たようですが、新たにその逆の問題が起きているようです。
単純に考えれば、入力されたアスキーコードをそのまま使えばいいというこ
とになりますが、色々事情があって別のプログラムにしているのでしょう。こ
のあたりはタイムマシンの設計者(本書の著者ではない)の意思を尊重するし
かありません。
BCD の数値を上位/下位に分ける方法は問48にもありましたが、プログラム
的にもう少し簡単な方法があります。問74にあったプログラムを逆用すればい
いのです。
CL レジスタの値はシフト命令の実行後も不変ですから、ループに入る前に
CL レジスタの初期値を4としています。また、 AL に BCD コードの上位が、
184
ADATA
DB
0,0,0,0,0,0
BCDDT
DB
12H,34H,56H
BCDAS
PROC
MOV
SI, OFFSET BCDDT
MOV
Dl,OFFSET ADATA
MOV
DX,3
MOV
CL,4
BCALP:
XOR
AX, AX
MOV
AH,CS:[SI]
ROL
AX, CL
SHR
AH,CL
OR
AX, 3030 H
MOV
CS:[DI],AX
ADD
Dl,2
INC
SI
DEC
DX
JNZ
BCALP
RET
BCDAS
ENDP
—アスキーコードに 変換され た 結果
—BCD による数値
—BCD による数値のあるアドレス
—アスキーコード数字が入るアドレス
—BCDDT のバイト数
—BCD をアスキーコードに変換
AH に BCD コードの下位が入るように工夫している点にも注意してくださ
い。
これで、白タイの隊員も無事拘束から解放されることでしょう。
185
閩
76
BCD をシフトする
— 、ワタシハニホゴへタナガイジデース。チョドイマニホノゲンカン
ナリタへツイタパカリデース。
ワタシウマレハフランスソダチハブラジル — アメリカ — インド — ドイツ—サウジア
ラビア -^ オランダ — エチオピア -> 中国 -> ペルー -> モンゴル — ケニア — 日本 -> ポーランド->イ
タリア — エジプト …… 。ソノアトハキオクニアリマシェーン。
ダカラマトモニシャべレルコトバナーニモナイ。セメテマシゴカンゼンニオ
ボエタイネ。ソコデシツモンスルアル。
レジスタノアタイヲ 2 バイスルトキ 「SHL AL,1 」 卜カシフトシマスネ。アレッテ
BCD ニモツウヨウシマスカ?
夕トエバ、 AL=5 ヲ 2 バイスルプログラムハコレデ 0K デスカ。
MOV
AL,5
SHL
AL,1
DAA
ドゾヨロシクオネガイモシァゲマス。
ドコデモガイジン(千葉)
■答- 1
ドモテイネナシツモンアリガトゴザマス。モシワケナイケドフツ
ノ ニホゴデカカセテモライマス。
ふう〜っ . 。カタカナに気を取られて、質問の内容を忘れるところでした。
それにしても、さすがに多国を渡り歩いているだけあって質問も鋭い点を突い
ています。というのは、このプログラムは正解のようで正解でないし、間違っ
ているけども結果は合っているという妙なものなのです。
まず、これを実行した結果はどうなるかというと、 AL レジスタニ 10 H とキチ
ンと2倍された値が得られます。したがって、ここでの値だけを見れば不正解
とはいえません。しかし、これを AL = 8 H で実行したらどうなるでしょうか。
結果が AL = 16 H となってくれればいいのですが、実はこれも AL=10 H となっ
186
てしまうのです。つまり、結果が正しくなる時もあるし狂う時もあるのです。
当然、これは間違った使い方ということになります。
DAA 命令というのは、あくまでも BCD 数値の加減算命令を実行した後にだ
け正常な働きをする命令です。しかし、それ以外の場合でも無意識 (?) に AL
レジスタの値を BCD 化しようとする実直な命令なのです。その結果、偶然にも
期待した値になることもあるし、まったく違った値になることもあるわけです。
したがって、このプログラムは次のように改めなければなりません。
MOV
AL,5
ADD
A し, A し
DAA
ちなみに、左シフトして2倍になるとよく言いますが、これは正確には二進
数を左シフトすると二進数表記で10倍(十進数表記で2倍)になるということ
です。つまり、何進数であれ左シフトすればその表記での10倍になっているの
です。試しに我々が日常使用している十進数で考えてみましょう。
1410 — 100 41000 — 10000 — 10000
5 -► 50 500 —► 5000 —► 50000 50000
実に当り前のことですね。 BCD というのは二進化十進数、つまり考え方とし
ては十進数です。シフトさせるのであれば4ビット単位でシフトさせなければ
なりません。当然、結果は十進数で10倍となり、 DAA をする必要はありません。
参考までに、3バイトの BCD 数値の左シフトを行ってみましょう。
DTBCD
DB
00,12 H,34H
卜 BCD による数値
SFT10
PROC
MOV
SI, OFFSET DTBCD
MOV
DX,2
—BCD 数値のバイト数
MOV
CL,4
LOOPS :
MOV
AX'CS : [SI]
XCHG
AL,AH
SH し
AX, CL
187
SFT10
CS : [SI],AH
SI
DX
LOOPS
CS : rsn'AL
プログラム実行後には 、 DTBCD 二 01 H 、23 h 、40 h となります。蛇足ですが、
100倍ならメモリ単位のブロック転送で処理できますし、右シフトをすれば結
果は1/10となります。
デハ ドゾ マシゴデ セカイ ノコ クサ イジ ンニ ナテクダサ〜イ……。
MOVINCDECJNZMOVRETi
188
閩
77
BCD 数値の四捨 5 A
ウヮッ!!
/ また仲間がやられてしまった。今度の相手はとても強い……。だいたい、アイツら4人
組だもんナァ。魔法を使うヤツもいるし、ケガを治すヤツもいる。おまけに戦うたびにますま
す強くなっていくようだ。
これじゃ、いくらこちらが頑張ってもかなうわけないよナ。おや、マタンゴおやじがイイ線
いってるぞ。うまいことアイツらを眠らせたようだ。そこだ、行けっ!!なぐれ、パンチだパ
ンチ!!そうだ、ボディ . ボディ!!
やったァ〜。全員倒したぞ〜。これで、アイツらの顔は二度と見ることはない。平和な世界が
戻った……卜卜、と思ったらアイツら生き返っちまった。
なんてイイ加減な世界なんだ。ここはデジタルの世界のはずなのに、まるで四捨五入の世界み
たいだ。
そういや、 BCD の数値を四捨五入するってのはできるんだろうか。たとえば、メモリを3パ
イト (6 桁)使って、前半の5桁を整数部、残り1桁を小数部とし、小数第1位四捨五入なん
ていうのはできるんだろう力、。
どうせ、オレたちの存在なんてゴキブリ以下なんだろうけど、それくらいは ハッ キリしておき
たいよナ。アイツらいくらでも生き返れるからいいけど、オレたち死んだらしまいのワビしい
人生なんだからザ。
スライムちゃん(テレビ界)
■答--
グチを言いたいのか質問をしたいのか、本音は不明ですが、勇者の一人とし
てスライムちゃんの気持ちがわからないわけでもありません。かなりハデに暴
れ回った経験がある以上、せめてもの罪ほろぼしに、無条件で BCD の四捨五入
を教えることにしましょう。
四捨五入とは、4以下切り捨て5以上切り上げですから、+ 5をして9以下切
り捨てと考えることができます。ですから、小数第1位四捨五入なら、 0.5 を足
して小数点以下を切り捨てればいいのです。
«小数第1位四捨五入の例〉〉
12.3 — 12.3 + 0.5 = 12.8 —12.0
12.7—►12.7+0.5 = 13.2 — 13.0
189
では、質問にあるように3バイト (6 桁)の BCD 数値の1桁目で四捨五入す
るプログラムを組んでみます。
— BCD データ
—四捨五入のため+ 5する
―キャリーフラグを退避
—1 桁目をゼロにする
—以下、通常の BCD 計算
四捨五入するのは1桁目ですが、桁上がりがあるかもしれませんから、計算
は全桁にわたって行わなければなりません。
ちなみに、単なる切り上げは零捨一入のことですから、+ 9をして切り捨てを
すればいいわけです。もちろん、二捨三入でも八捨九入でも自由自在です。い
かにも、スライムちゃんにふさわしいブログラムではないですか……。
DTBCD
DB
12 H,34 H,56 H
SISYA
PROC
PUSH
DS
MOV
AX.CS
MOV
DS,AX
MOV
BX,OFFSET DTBCD+2
MOV
AL,[BX]
ADD
AL,5
DAA
PUSHF
AND
ALJ1110000 B
MOV
[BX],AL
DEC
BX
POPF
MOV
AL,[BX]
ADC
AL,0
DAA
MOV
[BX],AL
DEC
BX
MOV
AL,[BX]
ADC
AM
DAA
MOV
[BX],AL
POP
DS
RET
SISYA
ENDP
19〇
閩
78
BCD 数値 x AL
AK 日、友人と 3 人でひなびた民宿へ泊まった。1人一泊1000円という安さだった。次の
ノじ日、ぼくは友人2人から1000円ずつ集めて、まとめてお金を払おうとした。すると、
バァさんが「また来ておくれ」と言って500円サービスしてくれた。3人で500円じゃ割り切
れないので、ぼくはこっそり200円ネコバパした。そして、残りをみんなで100円ずつ分けた。
結局、1人900円で泊まったわけだから、3人で2700円だ。それに、ぼくのネコパパした200
円を足すと……。アレツ、2900円しかない。確か、最初は3000円あったはずだ。どこかに落
としたのだろう力、。
ぼくは、コンピュータでこの謎を解決しようと思う。数値は BCD で3バイトを使うことにし
た。そうだ、色々な人数でも通用するようにしたほうがいい。ぼくは、人数はそれほど多くな
らないから AL レジスタで示すことにした。だから、 AL レジスタは十六進数の数値ということ
になる。
ということは、「3バイトの BCD の数値 XALJ ができればいいのだな。ぼくは、いつものよ
うに独り言をつぶやきながら、プログラムを組むことにした。でも、 BCD のかけ算ができな
かった . 。
セブンつ子(鳥取)
■答- .
数のマジックという言葉がありますが、とかく人間は数にダマされやすいも
のです。朝三暮四とは猿のこと、なんて思っていると痛い目に会うかもしれま
せん。
8畳の広い和室—畳そのものが極端に小さい
3 個で 9 割引— 3 割引 X 3 個
定価10000円を980円—500円くらいの商品に10000円の定価を付ける
合格率100%の予備校—1人が5校に合格すると4人が不合格でも合格率は100%
時ソバ、ねずみ講、減税と増税 . 、わかっていてもついついダマされそう
です。もっとも、今回のネコババの計算は自業自得ですが……。
ネコババ計算の解決は別として、『3バイトの BCD の数値 x AL 』 という計算
は正しくプログラムしなければなりません。ここでは、 AL レジスタの値が
BCD ではなく十六進数として扱われているので、足し算のループでかけ算を実
行します。
/ク/
KEKKA
DB
0,0,0
― かけ算の結果が入る
DTBCD
DB
01H,23H,45H
—BCD の数値
KAKBA
PROC
MOV
Dl, OFFSET
KEKKA
—結果エリアのクリア
MOV
CX,3
MOV
DL,AL
— DL = ループ回数(かける数 )
XOR
AX, AX
REP
STOSB
AND
D し , DL
JE
KAKRT
MOV
Dl, OFFSET
DTBCD
MOV
BL,[DI]
— BL = ( DTBCD )
MOV
BH,[DI + 1]
— BH =( DTBCD +1)
MOV
AH,[DI + 2]
— AH = ( DTBCD +2)
MOV
D し OFFSET
KEKKA
— 加算ループによるかけ算
MOV
CL,DL
MOV
CH,0
KBAL1 :
MOV
AL,[DI + 2]
ADD
AL,AH
DAA
MOV
[DI + 2],AL
MOV
AL,[DI + 1]
ADC
AL,BH
DAA
MOV
[DI + 1],AL
MOV
AL,[DI]
ADC
AL,BL
DAA
MOV
[DI],AL
LOOP
KBAL1
KAKRT :
RET
KAKBA
ENDP
(注) DS = ES=CS と仮定する
かけ算の結果は 「 KEKKA 」 からの3バイトに入ります。 BCD による最も単
純な計算例ですから、数のマジックでゴマ化されることもないでしよう。
192
BCD どうしのかけ算簾タイプ)
か
らっ風とカカア天下……とくりゃ、ウチの母ちゃんにピッタリ。暑さ寒さもなんのそ
の、強くたくましく頼りになる母ちやんだ。
北風がビュウビュウ吹いたって、絶対に倒れないドッシリした体格。ワシが安心して働けるの
も、この母ちゃんがいるからだ。給料が安くても文句は言わない。おまけに、料理はうまいし
運転もできる。
母ちゃんが病気になってもワシは抱えられないが、ワシが病気になると母ちゃんはヒョイと
抱えてくれるんだぜ。どうだい……カカア天下はいいだろう!!
でもな、いくら母ちゃんでもコンピュータだけはダメだ。これだけは教えてもらうことができ
ない。仕方ないので質問だ。
実は、 BCD でかけ算をやってみたいのだ。もちろん、問67にあるようなカツコイイ方法でだ。
全部を足し算のループでグルグル回すなんていうのはダメだぞ。なにしろワシはソフトハウ
スの部長という肩書だからな。
おっと、レベルの低いソフトハウスだなんて思わないでもらいたい。ワシは営業部長だからプ
ログラムは関係ないんだ。これはあくまでワシの趣味だ、し•ゅ•み……。
信じられないんだったら、母ちゃんに聞いてみな。
ワシは父ちゃん(群馬)
■答^- -
なになに…… 「追伸書き忘れたけど、母ちゃんは結構美人なんだぞ……」
だって。こうなると、質問というより母ちゃんの宣伝みたいな気もします。
なにはともあれ、すべてを信じて BCD のかけ算をカッコヨクやることにし
ましょう。ただし、問67の場合のようにプログラムを組むことはできません。
なぜなら、 MUL 命令を使うためにはニブル単位( 4 ビット単位)のデータをバ
イト単位に展開しなければならないからです。
問76でも説明したように、 BCD では数値を4ビット単位で扱うことが原則
です。したがって、 BCD のかけ算は筆算による十進数のかけ算と同じような感
覚でプログラムを組むことになります。
193
« プログラム的筆算によるかけ算の例〉〉
123
X 456
738 — 123X6 (足し算のループで行う)
6150 — 1230X5 (足し算のループで行う)
492 — 123X4 (足し算のループで行う)
56088
では、これを実際にプログラミングしてみましょう。このプログラムでは、
ADATA (3 バイト:十進数で6桁 ) x BDATA (3 バイト:十進数で6桁)=
KEKKA (6 バイト:十進数で12桁)の計算を行っています。
KEKKA
DB
0,0,0,0,0,0
DUMMY
DB
0
ADATA
DB
0,01 H,23H
BDATA
DB
0,04 H,56H
ADA10
DB
0,0 ,0,0
KAKEX
PROC
PUSH
DS
PUSH
ES
MOV
AX,CS
MOV
DS,AX
MOV
ES,AX
MOV
D し OFFSET KEKKA
XOR
AX, AX
MOV
CX,3
REP
STOSW
MOV
SI,OFFSET ADATA
MOV
Dl,OFFSET ADA10+1
MOV
CX,3
REP
MOVSB
MOV
Dl,OFFSET ADA10
MOV
DX,3
MOV
CL,4
LOOPS :
MOV
AX,[DI]
XCHG
AL,AH
SHL
AX, CL
— ADATA を4バイトとして扱うためのダミー
<-ADATAX10 が入る
—結果をクリア
— BCD 数値のバイト数
—ADATAX10 を ADA10 に用意する
m
MOV
INC
INC
DEC
JNZ
MOV
MOV
MOV
MOV
KAKLP : MOV
MOV
CALL
MOV
SHR
SHR
SHR
SHR
MOV
CALL
DEC
DEC
DEC
JNZ
POP
POP
RET
KAKEX ENDP
KAKSS PROC
AND
JE
MOV
MOV
KAKSL : PUSH
PUSH
MOV
ADD
DAA
MOV
DEC
[ 叫 , AH
SI
Dl
DX
LOOPS
[ 叫 , AL
SI,OFFSET BDATA + 2
BX,OFFSET KEKKA+5
DX,3
Dl,OFFSET ADATA + 2
AL,[SI]
KAKSS
AL,[SI]
AL ; 1
ALJ
ALJ
AL,1
Dl,OFFSET ADA10 + 3
KAKSS
SI
BX
DX
KAKLP
ES
DS
AL, 00001111 B
KAKRT
CL,AL
CH,0
BX
Dl
AL ,[ DI ]
AL,[BX]
[BX],AL
BX
<-Sl = かける数のエンドアドレス
卜 ( KEKKA ) 〜 ( KEKKA +5)= 計算結果が入る
—かけるバイト数
—桁ごとのかけ算
195
DEC Dl
MOV AL,[DI]
ADC AL 』 BX]
DAA
MOV [BX],AL
DEC BX
DEC Dl
MOV AL,[DI]
ADC AL,[BX]
DAA
MOV [BX],AL
DEC BX
DEC Dl
MOV AL # [DI]
ADC AL,[BX]
DAA
MOV [BX],AL
POP Dl
POP BX
LOOP KAKSL
KAKRT: RET
KAKSS ENDP
桁ことのかけ算といっても、1バイトが2桁分に相当していますから、すべ
ての桁を同じように扱うわけにはいきません。先ほどの例でいうと、普通の筆
算では2段目は615となりますが、1段目とは「738 + 6150」という計算です。
つまり、2段目の値は10倍して加算しなければならないわけです。もちろん、
3段目は100倍して加算することになりますが、これはメモリを1バイトずら
すことで対処できます。しかし、次の段があればやはり10倍した値が必要にな
ります。
そこで、最初に ADATA (かけられる数)の値を10倍したものを用意してお
くと、かける数の上位4ビットも下位4ビットと同じような計算処理ができま
す。たたし、10倍したものは4バイトのメモリを使いますから、プログラムは
4バイト分の計算 ( KAKSL 内における処理)をしなければなりません。さら
に、このプログラムを上位/下位共通に使用するためには、 ADATA のほうも
196
4 バイトにしておく必要があります。そのため 、 AD AT A の手前に DUMMY
として1バイト(中身 = 0) を確保しているわけです。
プログラム ( KAKSS ) を共通化せず、下位4ビット用に3バイト分の計算を
するプログラムを用意すれば、この DUMMY は不要です。このあたりの判断
は、営業部長の父ちゃんにまかせることにします。
197
琶
80
BX レジスタ®1を BCD に変換
pp ラミツド•パワ_……。この謎のベールに包まれたパワーを確認するため、私はクフ王
の眠る巨大なピラミツドへとやって来ました。
私は、すでに30年の歳月をかけて、この神秘のパワーを求める物理学的計算式を発見したの
です。それは、あらゆるパワーが複雑に、しかもバランスよく絡み合った、まるで生命体のよ
うな計算式でした。
しかし、その計算式には1つだけ未知数が存在しているのです。これは、現在の数学では発見
されていない数値、たとえていうなら i (2 乗して一1になる数値)のようなものです。私は、
その未知数に Pp (ピューピー)と名付け、この計算式を成立させたのです。
では、この Pp の正体だけを明かしておきましょう。 Pp とは、かけても割っても1になるとい
う数値です。例をあげてみます。
543 XPp=l 543 + Pp = l
つまり、あらゆる数値が1に収束してしまうのです。この未知数 Pp の存在を裏付けるため、
ピラミッド内部のアチコチで Pp の測定をしています。その時、マシン語で BCD の数値と十
六進数の BX レジスタの値との高速乗算をしたいのです。
ピラミッド内部より、絶大なるご協力を要請します。
デタラム•ぺテム(エジプト)
■答-^
ピラミツドだけでなく、単なる四角錐にも謎のパワーが i 必められているそう
ですが、そのパワーとは一体なんなんでしょうか。卵が腐らないとか、頭がよ
くなるとか、四角錐にまつわるウワサは真実味にあふれています。
そこに突然登場した、 この Pp (ピューピー)なる未知数…… 。 どこまで 本当
で、どこまでウソなのか、まったくわからないところにインチキの魅力があり
そうです。
しかし、ここでは 『BCD の数値 XBX』 だけが問題です。高速というからに
は、問78の方法(足し算のループ)では不満なはず。どうにかして、 BX レジ
スタの値を BCD イ匕して、問79のプログラムが使えるようにしなければなりま
せん。
198
ここにあるプログラムは、 BX レジスタの値を BCD に直し、問79にあるプ
ログラムの 「 BDATA 」 に入れるというものです。つまり、このプログラム
( HLBCD ) を コールし てから問79のプログラムを コール すればいいわけで
す0
HLBIT DB
HLBCD PROC
PUSH
MOV
MOV
XOR
MOV
MOV
MOV
MOV
MOV
MOV
INC
MOV
INC
MOV
MOV
HLBLP : MOV
SHR
JNB
CALL
HLB01 : MOV
ADD
DAA
MOV
DEC
MOV
ADC
DAA
MOV
DEC
MOV
ADC
0 , 0,0
DS
AX,CS
DS,AX
AL,AL
SI,OFFSET BDATA + 2
[SI],AL
[SM], AL
[S 卜 2],AL
BX,OFFSET HLBIT
[SI],AL
BX
[BX],AL
BX
BYTE PTR [BX]J
CX,16
BX,OFFSET HLBIT+ 2
DX,1
HLBOl
BTADD
AL,[BX]
AL,AL
[BX],AL
BX
al,[bx]
A しし
[bx],l
BX
AL,[BX]
AL,AL
—ビット別加算データ
—変換先
— ( HLBIT ) 〜 ( HLBIT +2) の初期化
— CX = 変換ビット数 (16 ビット)
—ビット=1のところだけビット別加算デ-夕を加算
—ビット別加算データを2倍する
199
DAA
MOV
[ BX],AL
LOOP
HLBLP
POP
DS
HLBCD
RET
ENDP
BTADD
PROC
MOV
AL ,[ BX ]
ADD
AL ,[ SI ]
DAA
MOV
[ SI],AL
DEC
BX
MOV
AL ,[ BX ]
ADC
AL ,[ SI -1]
DAA
MOV
[ SI -1 ],AL
DEC
BX
MOV
al ,[ bx ]
ADC
AL,[S 卜 2]
DAA
MOV
[ SI -2 LAL
MOV
BX,OFFSET HLBIT + 2
BTADD
RET
ENDP
—ビット別加算データを変換先に加算
プログラムの 考え方は、 BX レジスタを 各ビット別に BCD 化して、 16 ビット
分加算していくものです。ビット= 1 の場合に加算する値 (BCD 値)は次のよ
うになります。
ビット0 = 00,00,01
ビット1 = 00,00,02
ビット2 = 00,00,04
ビット3 = 00,00,08
ビット4 = 00,00,16
ビット5 = 00,00,32
ビット6 = 00,00,64
ビット7 = 00,01,28
ビット8 =00,02,56
ビット9 =00,05,12
ビット10 = 00,10,24
ビット11 = 00,20,48
ビット12 = 00,40,96
ビット13 = 00,81,92
ビット14 = 01,63,84
ビット15=03,27,68
200
今回は、これらのビット別データを計算によって求めていますが、メモリに
データとして用意しておくと、「ビット別加算データを2倍する」代わりにその
データアドレスを変更するだけで済むので、メモリ効率は悪くなりますがス
ピードはアップします。
また、問47のような考え方で、 BX レジスタの 値を10000、1000、100、10 で
減算するように割り、その商を BCD 化していくという方法もあります。どちら
の方法が処理が速いかは、その時の BX レジスタ の値によって変わってきます
ので、状況に応じながら使い分けてください。
これで Pp (ピューピー)が発見できるのであれば、盆と正月と誕生日とクリ
スマスが一度にやって来るでしょう。ついでに、宝くじにも当たるかもしれま
せん . ネ!?
201
n_
1^ ツヒツヒツヒ . 〇
^ わたしや魔女じやよ。ホラ、あの黒いとんがり帽子をかぶって、魔法のホウキにまた
がって空を飛ぶ魔女じや。有名じやから、知っておるじやろ。
でも、この魔法のホウキが、実はマイクロコンピュータに制御されていたなんてことは知らん
じ やろ。 この ホウキの秘密は、 この長い 柄にあるの じ や。 この 柄には いくつかの バージョンが
あってな、魔女のランクによって交換されるシステムなのじやよ。
わたしや、ランクの低い三等魔女じやが、秘かにマシン語を覚えて、この柄のプログラムを変
えてしまおうと思っているのじや。
そこで質問じ や。 このホウキの柄と刷毛(はけ)の関係のように、マシン語コードを分割して
使うことがあるそうなのじやが、そんな魔法のような使い方ができるのじやろか、というのが
質問なのじや。
魔女だからといって、イジワルはしないでおくれ……。
西洋の魔女(ノー トルダム)
■答--
確か、ノートルダムに住んでいるのは‘せむし男’のはずでは……? それにし
ても、現代の魔女はマシン語まで勉強しなければならないとは、本当にご苦労
なこととしか言いようがありません。
質問があまりにも魔女的なので、もう少し普通の人間にもわかるように、問
題を具体化してみましょう。
あるマシン語コードがあったとして、そのコードをうまく分割して別なマシ
ン語コードとして使うというわけですが。確かに方法としてはあります。
といっても、むやみに分割しても意味がありません。例えば、条件によって
AX レジスタに0または0以外の数値を格納するという場面にしばしば出会う
ことがありますが、これをプログラムすると次のようになります。
INT 21 H
JNB C 0 DE 2
202
C 0 DE 1 :
MOV
AX ,0 FFFFH
JMP
LB 001
C 0 DE 2 :
XOR
AX , AX
LB 001 :
このような場合 「MOV AX , OFFFFHJ のオペランドである 0 FFFF H が、特
に0以外のどのような数 tt : でもよいのであれば、このオペランド部分を rxoR
AX , AX 」 のマシン語コードである 0 C 031 H とすることによって次のようなプロ
グラムが組めるわけです。
INT
21 H
JNB
$+3
MOV
AX ,0 C 031 H
これは、キャ リーフラグの状態によって 、 「MOV AX ,0 C 031 H — AX = C 031
H 」 または、 「XOR AX,AX — AX = 0」 となり、プログラムの目的は果たせ
ることになります。しかも4バイトのメモリの節約になるのです。
ほかにも、色々あるでしょうが、それは魔女さんへの課題としておきます。
うまくいけば、三等魔女のホウキも一挙に一等魔女のホウキに化けられるかも
しれません。
203
82
BCD どうしの酌算( II る数の棚!固定)
人86号が いいだろ うか、それとも鉄腕インテル がいい かな、やっぱりハチ ロクマンに
しようか……。
ネーミングが決まらないから、なかなか設計にかかれない。人間が月へ行く時代だというの
に、いまだに本物のロポットが作れないというのは、はなはだ遺憾である。自動車 メーカーに
は、部分的にロボットらしきものがあるが、いつまで待ってもあれは歩かないようだ。
マ、順序としては鉄人86号から完成させるのが筋だろうな。もちろん、 1 C は8086系を使うこ
とになる。では、さっそく設計にかかろう。
……ウ〜厶、電波を受けてから手を動かすためには、高速な割り算をしなければならないの
か。一応、割る数は8888に固定しよう。割られる数は不定だが、8桁だな。ということは、
BCD による筆算タイプの割り算でないと無理だ。
しかし、減算ループによる割り算ならできそうだが、筆算のようにするには難しそうだぞ。設
計の前に教えてもらわなければなるまい。
鉄人のために、よろしく頼む。
敷島博士(山梨)
■答- .
鉄人86号……。名前はカッコイイけど、完成した鉄人が活躍する場所を捜す
のに苦労しそうです。
まず、相手がいない。今どき、わざわざ目立つロボットを作って悪いことを
しようなどという悪人はいないでしょう。おまけに、下手に歩けば道路はこわ
すし電線にも引っかかる。それではとロケットが火を噴けば、周りは火事になっ
て大惨事……。
これでは、せっかくの夢がこわれそうです。余計なことを考えずに、 BCD の
筆算タイプの割り算を実現することにしましょう。
かけ算の時もそうでしたが、 BCD では割り算を二進数的な考え方で実行する
ことはできません。そのため、商の桁ごとに減算のループによる割り算を行う
ことになります。
今回は、割られる数が8桁、割る数が8888に固定されているので、4バイト
の BCD 数値を 2 バイト (4 桁)の BCD 数値で割るという計算ですが、割られ
る数、割る数の桁数は割り算の重要なポイントです。
商の桁数二 8-4 + 1
また、 BCD の計算では、その桁の商がメモリの上位4ビットに入るか、下位
4ビットに入るかも区別しなければなりません。今回の場合は、商が5桁です
から メモリの 下位4ビッ ト から入れることになります。
ここではサンプルデータとして割られる数=10967792としていますが、もし
割り切れない数となった場合は小数点以下切り捨てです。ただし、小数点はユー
ザー側の区切りですから、ダミーのメモリ(中身 =0) を追加すれば、小数点
以下何位まででも求めることができます。その場合、割る数 ( BDATA ) や商
( KEKKA ) のメモリも計算に合わせて追加しなければなりません。
割り算の最後は常に切り捨てですから、四捨五入したい場合は問77の方法で
自由にしてください。
KEKKA
DB
ADATA
DB
BDATA
DB
WARIX
PROC
PUSH
MOV
MOV
MOV
MOV
CALL
CALL
CALL
POP
RET
WARIX
ENDP
WARI2
PROC
MOV
CALL
0 , 0,0
10H,96H,77H,92H
88H,88H,0,0
DS
AX,CS
DS,AX
SI,OFFSET KEKKA
CL,0
WARM
WARI2
WARI2
DS
CL,0
WAXCC
—商が入る
— 割られる数 ( 8 桁)
— 割る数(上位 4 桁)
下 4 桁は桁合わせのためのダミー
— CL = 桁ごとの商
—下位4ビットの商を求める
—上位4ビット/下位4ビットの商を求める
—上位4ビツト/下位4ビットの商を求める
205
WARI 2
WARM
WARM
WAXCC
WACLO :
SBCLO :
WAEDO :
ADCLO :
SH し
CL ,1
SH し
CL ,1
SH し
CL ,1
SHL
CLJ
CALL
RET
ENDP
WARM
PROC
CALL
WAXCC
MOV
[ SI],CL
INC
RET
ENDP
SI
PROC
MOV
Dl,OFFSET ADATA + 3
①
MOV
CLC
BX,OFFSET BDATA + 3
②
MOV
CH ,4
③
PUSH
Dl
PUSH
BX
MOV
AL ,[ DI ]
SBB
DAS
AL ,[ BX ]
MOV
[ DI],AL
DEC
Dl
DEC
BX
DEC
CH
JNZ
SBCLO
POP
BX
POP
Dl
JB
WAEDO
INC
CL
JMP
WACLO
MOV
CLC
CH ,4
③
MOV
al ,[ di ]
ADC
DAA
al ,[ bx ]
— 商を上位 4 ビットに移す
—桁ごとの商を求める割り算
—CH = BCD 数値のバイト数
―減算 ループに よる割り算
—減算しすぎた分を加算する
206
HLRRD :
WAXCC
MOV
岡 , AL
DEC
Dl
DEC
BX
DEC
CH
JNZ
ADCLO
XOR
A し , AL
MOV
DX ,4
PUSH
CX
MOV
CL ,4
INC
BX
MOV
AH ,[ BX ]
ROR
AX , CL
ROR
A し , CL
MOV
[ BX],AH
DEC
DX
JNZ
HLRRD
POP
CX
RET
ENDP
③
卜割る数を次の桁用に右シフトする
なお、プログラムを実行すると、割られる数 ( ADATA ) は割り算の余りとな
り、割る数 ( BDATA ) は破壊されます。必要があれば、退避してから実行して
ください。
そういえば、敷島博士の写真が同封されていましたが、年老いて、博士とい
うよりまるで仙人のような風貌でした……。
2(yj
琶
83
内部割獅と外部割 D 秘
- こをどこだと思いますか?咲き乱れる美しい花。夢と理想と現実が完全に一致した
w 憧れの都……。そうです、ここは天国です。下界でも、『天国よいとこ一度はおいで。
酒はウマイし、ねェちゃんはキレイだ』と歌われていますネ。
とはいえ、ここは一度来たら二度と下界へは帰れませんから注意してください。下界に未練が
あるうちは決して来てはなりません。な一に、無理しなくても誰でもいつかは来られますか
ら、あせることはないのです。
もちろん、ここではパソコンを楽しむことも自由自在です。プログラムだって好きなだけでき
ます。実は、私は下界では割り込みが得意でしたが、ここに来て初めて8086を使うようになっ
たのです。ところが、8086には外部割り込みと内部割り込みがあるというじゃないですか。こ
れまでは外部割り込みだけでしたから、内部割り込みがどういうものなのか、ピンと来ないの
です。どうぞ、よろしく。
ア、返事はテレパシーで送ってください。テレ•ナンバーは (03)16000-9801 です。
天馬天之介(天国)
■答--
なんとなく、こわ〜いような気もする質問ですが、これ普通の手紙で来たん
ですョ。しかも、封筒の裏側にはちゃんと住所が……。アレ? よく見れば、
『キャバレー天国』なんて書いて あるじ ゃないで すか。驚かさ ないで く /ど さい。
私は、いたって気が小さいんですからネ。
さて、他の CPU で外部割り込みを使ったこと が あれば、 ユーザーが 使う内部
割り込みは非常に簡単です。そもそも、内部割り込みは「ソフトウヱア割り込
み」とも言って、 プログラム 側から割り込みを発生させるものなのです。つま
り、 プロシージャ 感覚で コールして 使うのです。
ただ、 CALL 命令がアドレスでコールするのに対して、内部割り込みは INT
命令で割り込み番号を設定してコールします。
♦プロシージャコール
CALL PROC 1 :アドレス指定で コールす る
♦内部割り込みの例
INT 21 H :割り込み番号で コールす る
2 〇8
内部割り込みには、ユーザーが INT 命令で発生させるほかに、 CPU が使う
ために予約しているもの、 MS - DOS などのシステム側で予約しているもの、
8086を搭載した機種で予約しているものなどがあります。
したがって、ユーザーが内部割り込みを使う場合には、ユーザー用に解放さ
れている割り込みを使うことになります。例えば、 PC -9801 などでは 、 「INT 40
H」 〜 「INT 7 FH 」 となります。
ここで、 INT 命令の動作を確認してみましよう。
1•••フラグをスタックへプッシュする
2 ••.割り込みフラグとトラップフラグをクリアする
3 •••コードセグメント ( CS ) をスタックへプッシュする
4 ... CS へ割り込み番号に対応するセグメントアドレスを
ベクターテーブルから ロー ドする
5•••インストラクション•ポインター ( IP ) をスタック
ヘプッシュする
6 •_ . IP へ割り込み番号に対応するオフセットアドレスを
ベクターテーブルから口ー ドする
割り込みプロシージャを組む時には、フラグがプッシュされた後に、インター
ラブトフラグがクリアされることに注意してください。なお、割り込みプロシー
ジャに対するリターン命令は 「 IRET 」 が使われます。
ユーザーの作っ た割り込みプロ シー ジャは何らかの方法で、空いている割り
込み テーブルに エントリーを登録しなければなりませんが、 MS - DOS には割
り込みプロ シー ジャのエントリーを登録するファンクシヨンが用意されていま
す。通常はこれを利用して登録するといいでしょう。ただし、割り込み処理は
機種に依存する部分が多いので、機種の特性を十分に把握した上でプログラム
を組んでください。
それでは、この テレパシーが『キャバレー 天国』に届くことを 祈つ ておりま
す 0
2〇9
閩
84
MAKE の利用
う一や一た あ 一っ!!
求道者の道はつらい。常に正しい道を求めなければならない。しかも道は自分で切り開かねば
ならない。おっと……いけない、つい弱音をはいてしまった。えっ?何の求道者かって、も
ちろん、マシン語道だ、拙者はマシン語歴1年、自称、マシン語道迷人位の位を持っておる。
ところで、困ったことに、 MS - DOS の外部コマンドに MAKE を発見してしまった。マシン語
開発にはとても便利であるそうだが、どうも不安でしょうがない、なにが不安かって、何が不
安かわからないから困っておるのだ。求道者としては MAKE を使うべきであることはわかっ
ている。そこで相談だが、この不安を取り除いてはくれないだろうか?
そうしたら、秘伝中の秘伝をさずけてやろう。信用されないと困るので、少しだけ内容を公開
してやる。その秘伝とは、く意志を持った無だ〉。どうだ、まいったろう。
どういうことかって、そこまでは公開できない。後は、この不安を取り除いてくれてからの話
だ。では、よろしくたのむ!!
マシン語迷人(人間界)
■答- -
秘伝中の秘伝を公開してくれるとなると、不安を取り除いてあげなければな
らないでしよう。でも、内容がナイヨウなので不安ですが . 。
さて、 MAKE を発見したとなるとマシン語の腕前もかなりのもの、プログラ
ム開発にも余裕が出てきたところかもじれません。 MAKE は、次のようにすれ
ば起動されます。
A>MAKE くメイクフアイル名〉
もちろん、 MAKE を起動する場合、 「 MAKE . EXE 」 という実行ファイルが
必要となります。さらに、 MAKE を実行する手順を示したメイクファイルを作
らなければなりません。
このメイクファイルは 「 CONFIG . SYS 」 と同じように、テキストファイルで
すから、エドリン (EDLIN) などのエディタを使って、決められた書式で記述
し作成します。なお、メイクファイル名は、開発ブログラムと同じ名前を、拡
張子を付けないで用いるのが慣習となっているようです。
MAKE で最も重要なのが、このメイクフアイルです。メイクフアイルの書式
は次の通りですから、参考にして〈ださい。
関連ファイル名の間は最低
I つのスペースで 区切る
目的ファイルは丨つ 関連ファイルが丨行に入らない場合
だけ許される 行の終わりに (¥) をタイプする
1
〈目的ファイル名〉:〈関連ファイル名〉〈関連ファイル名〉 .
〈コマンド〉
t !
TAB またはスペースを f
コマンドの 前に入れる MS-DOS のコマンド
複数指定可能
目的ファイル、関連ファイル、そしてコマンドを組み合わせて1つの作業記
述単位となります。この作業記述は1つのメイクファイル中、いくつ入れても
かまいませんが、作業記述と作業記述の間は、最低1行は、空けなければなり
ません。また、各ファイルが、メイクファイルと同じディレクトリにない場合
には、パス名が必要になります。
MAKE は、目的ファイルの作成日時以後に、各関連ファイルに修正があれば
コマンドを自動的に実行するようになっています。また、目的ファイルが存在
しない 場合にもコマンドを実行します。もし、目的ファイルが存在し、かつ関
連ファイルに修正がなければコマンドは実行されません。これだけでは不安を
解消できそうにもありませんから、実際のメイクフアイルの例を示しておきま
しょう。
211
サンプル ー 1
TEST1.0BJ : TEST1.ASM
MASM TEST1;
TEST1.EXE : TEST1.0BJ
LINK TEST1;
サンプル ー 2
TEST1.0BJ : TEST1.ASM TEST 卜 2.ASM TEST1-3.ASM TEST1-4.ASM
MASM TESTl;
T00L1.0BJ : T00L1.ASM
MASM T00L1;
T00L2.0BJ : TOOL2.ASM
MASM TOOL2 ;
TEST1.EXE : TESTI.OBJ TOOLl.OBJ T00L2.0BJ
LINK TEST1 T00L1 TOOL2,,/MAP;
MAPSYM TEST1
これで不安を解消できたでしようか?もっとも、一番の方法は知識を身に
付けるのではなく、実際に使ってみることですが……。
212
||
85
BCD に関するミニ•テクニック
A 間はコンピュータを作った。そして、それは人工知能へと発展しつつある。最近では
ファジィ理論という、人間らしい曖昧さを求めた研究も盛んに行われているというで
はないか。つまり、人間は自分と同じことをコンピュータにさせることで、生命を創造した神
になろうとしているのだ。
……だが、おいらの存在を忘れてもらっちゃ困るぜ。コホン!!おいらはコンピュータなどに
は絶対にマネのできない第三の知能さ。おいらの正体はまだ発見されていないようだが、誰で
もおいらの存在は知っているんだ。
おいらの名は『夢 J ……。夢を司る脳に住んでいるのさ。いくらコンピュータが人間のマネを
したところで、夢は見れまい。そこに神の偉大さがあるのだ。
だけど、おいらにも夢がある。それはおいらの存在をコンピュータ化してもらうことなんだ。
そのためには、 BCD どうしの比較やゼロチェックが自由自在に、しかもスバヤクできなけれ
ばならない。
人工夢脳のために、こういった BCD のミニ•テクを公開する気はないだろうか。もっとも、
それは人工夢脳へのスタートに過ぎないが……〇
夢見る夢(夢脳)
■答- •
近くて遠い夢の国……。
行けそうで行けない夢の国……。
現実のようでどこかが違う夢の国……。
夢をプログラムで実現できるかどうかはわかりませんが、その前に夢を録画
するビデオを開発してほしいものです。見ている時は真実そのもの、しかし実
際にはデタラメで支離滅裂でウソと幻に包まれたナゾの世界……。そのナゾの
解明に役立てるなら、 BCD のミニ • テクなどいくらでも公開しましょう。
(1) BCD どうしの比較
基本的には減算をすればいいのですが、下位桁から減算をしていくと全メモ
リを減算しないと比較できません。人間的な思考法では、上位桁から比較を
するほうが自然です。このプログラムは 「CMP DI ( BCD のアドレス ), SI
( BCD のアドレス)」を実行し、ゼロ/キヤリーフラグで判定を示すもので
213
す。例えば 「 CMP ①,②」をしたければ、 DI レジスタニ OFFSET
ADATA 、 SI レジスタ =OFFSET BDATA として、 AX レジスタにデー
夕 • セグメント値を格納して CPBCD をコールします。
ADATA
DB
12H ; 34H / 56H / 78H / 90H / 12H
BDATA
BD
11H / 22H / 33H / 44H / 55H / 66H
CPBCD
PR0C
PUSH
DS
PUSH
ES
MOV
DS'AX
MOV
ES,AX
MOV
CX,6
CLD
REPZ
CMPSB
POP
ES
POP
DS
RET
CPBCD
ENDP
—CX=BCD データのバイト数
(2) BCD のゼロチェック
すべての桁(メモリ)がゼロかどうかを調べるわけですが、これも上位から
調べるほうが人間的でしよう。 DI レジスタに調べたい BCD のオフセット
アドレスを入れ、 AX レジスタにセグメント•アドレスをセットして コール
してください。
BCDZF
PROC
PUSH
ES
MOV
ES , AX
XOR
AX, AX
MOV
CX,6
CLD
REPZ
SCASB
POP
ES
RET
BCDZF
ENDP
<-AX にデータ • セグメント値、 DI にオフセット•アドレスを格納してコール
— BCD データのバイト数
214
⑶ BCD の符号について
BCD の数の中には符号を含むことができませんから、符号が必要な場合に
は符号用のメモリを1バイト用意しなければなりません。例えば、0ならプ
ラス、1ならマイナスと決めておいて、加減算の場合にはその符号と照らし
合わせてから実行するようにするのです。
ただし、計算を加減算だけに限定すれば、符号付き数値のように扱うことも
できます。例えば、2桁の BCD 数値で15とあれば、85を一15と考えても
いいわけです。
20-15=05
20+85 = 05 —100以上は計算されない
このような符号変換は、いわば BCD 版 NEG 命令ということになります。
次のプログラムは3バイト用の BCD 版 NEG 命令です。 AX レジスタに
データ•セグメント•アドレス、 DI レジスタに BCD 数の最下位アドレス
を入れてコールしてください。
BCNEG
PROC
PUSH
DS
CLC
MOV
DS,AX
MOV
CX,6
BNGLP :
MOV
AL,0
SBB
AL,[DI]
DAS
MOV
[DI ] , AL
DEC
DI
LOOP
BNGLP
POP
DS
RET
BCNEG
ENDP
いずれも大したテクニックではありませんが、 BCD 数値を自在に扱うための
基礎として覚えておくと便利です。その程度ですから、これが夢の人工夢脳の
開発に役に立つことは夢にも思えません……。
215
費
86
テーブル処理で複雑な計算を
#浪……。そこには未知のものに出会える夢がある。しかし、最近はテレビが発達しすぎ
乃乂 たせいで、夢が減ってしまった。
昔は『知床旅情』なんていう歌は、北海道へ旅した者が覚えてくる歌だったのだ。だから、こ
の歌がテレビを通じて流行ったとたん、夢が1つ消えた。
かつて、私は日本最北端の島、礼文島を旅した。ユースホステルでは、元フォークグループの
若者が歌を教えていた。それは、『旅の終わり』、 r 島を愛す』という2つの歌だった。これら
は、少なくともメジャーな歌にはならなかった。
もしかすると、この歌はもう誰も知らないかもしれない……。私は、ときどき口ずさんでは、
たった一人の優越感に浸っている。
私は、さすらいのプログラマー……。もちろん、かけ算は知っている。実は X 2 を多用するプ
ログラムがあるのだが、毎回計算しているので時間がかかる。きっと、もっといい方法がある
と思うのだが、現状ではわからない。
しかし、マシン語には未知のテクニックを発見できる夢がある。まるで放浪の旅をしているよ
うだ。私は、そんなマシン語が好きだ。
さすらい人(礼文島)
| W - •
テレビというのは、夢を与えてくれているようで、実は夢を奪っているので
す。なぜなら、夢は想像の中から生まれるものだから……。
マシン語の世界は限りない想像の世界です。そこには、高級言語では味わう
ことのできない未知の魅力と無限の可能性があります。もしかすると、最も身
近な未踏の秘境かもしれません。
……が、マシン語で秘境探検をするには発想の転換が必要です。この X 2 も、
多用するからにはかけ算処理を省きたいものです。次のプログラムは、 AL レジ
スタ (0 〜 255) を2乗し、その結果を DX レジスタに求めるというものです。
プログラム自体は、問27でジャンプ•テーブルとして用いたものと似ていま
す。しかし、アイデアは似ていても内容はまったく違います。さらに、この X 2
という計算も見本の1つにすぎません。この用法の本当の価値は、複雑な計
216
KDATA
DW
0,1,4,9,16,25
DW
36,49,64,81,100
DW
63504,64009,64516,65025
XTIMX
PROC
MOV
AH,0
SH し
AX,1
MOV
SI,OFFSET KDATA
ADD
SI,AX
MOV
DX,[SI]
RET
XTIMX
ENDP
— 0 〜 255 を 2 乗した数値を
データとして用意しておく
— AL 2 の結果を DX に求める
( 注) DS=CS と仮定する
算をさせた場合に現れてくるのです。
また、計算結果を直接 BCD にすることもできます。つまり、テーブルの内容
に工夫を凝らせば、いくらでも応用の範囲は広がるということです。人跡未踏
のテク ニッ クというわけではありませんが、 マシン 語のちょっとした秘境とい
えるでしょう。
しかし、元の値が BCD の場合は、簡単にテーブルを利用できません。テープ
ルは十六進数のアドレスで示されますから、 BCD のままでは虫喰いテーブル
( A 〜 F のあるアドレスを使用しないテーブル)となってしまうからです。そこ
で、參考までに〇〜65535の BCD 数値を十六進数に変換し、 BX レジスタに入
れるプログラムを載せておきます。
BCDDT
DB
06H,55H,35H
—BCD の数値
BCDHL
PROC
MOV
SI, OFFSET BCDDT
XOR
BX,BX
MOV
AL,[SI]
MOV
CX, 10000
CALL
KAI4B
—10000 の位の計算
MOV
AL,[SI + 1]
217
AL, 000011 11B
CX
BX,AX
PROC
PUSH AX
SHR AL,1
SHR ALJ
SHR ALJ
SHR ALJ
CALL KAI4B
POP AX
RET
ENDP
MOV CX, 1000
CALL JOI4B
MOV CXJ00
CALL KAI4B
MOV AL,[SI + 2]
MOV CX,10
CALL 」 014 B
AND 000011 11B
MOV C し AL
ADD BX,CX
RET
ENDP
BCDHL
JOI4B
JOI4B
KAI4B
KAI4B
—1000 の位の計算
—100 の位の計算
—10 の位の計算
卜 1 の位の計算
- 上位 4 ビットの計算
— 下位 4 ビットの計算
( 注) DS=CS と仮定する
このプログラムを利用すれば、例えば「〇〜99の BCD 数#:」 — 「計算結果=
6バイト (12 桁)の BCD 数«:」などといったテーブルも簡単に実現できます。
もちろん、テーブルのために使用するだけでなく、単なる変換ルーチンとして
BCD 数値のままでは不便という場合に活用してもかまいません。
テーブルというのは応用範囲が大変広いテクニックですから、 プロ グラムが
R N B/IULDETN
p A c ^ A R E
218
複雑になったりダラダラと長くなりそうなときは、テーブル化を検討する価値
があります。もしかすると、まったく新しい用法や秘術に出会えるかもしれま
せん。
『新テクの陰に テーブル あり』
これも、マシン語の極意の1つといえるでしよう。マシン語にはこのように
メジャーなテクニックもあれば、日陰の鈴蘭のようなマイナーなテクニックも
あります。私も、そんなマシン語が好きです . 。
219
驛驟驟驟驟黎驟驟獅
1 . ニモニック表のオペランドで使われている記号の意味
2 . 8086のレジスタ紹介
3 . フラグ記号の意味
4 . フラグの名称
5 . クロック記号の意味
6 . オペレー シヨ ンコード •フイ ールド
7 . 8または16ビット汎用レジスタの選択
8 . セグメント.レジスタの選択
9 . メモリ•アドレッシング
1〇 . 8086 ニモニック ー覧表(機能別 アルファベット 順)
10-1 ……加算命令
10-2 . 減算命令
10 - 3 . 乗算命令
10-4 ……除算命令
10-5 ……データ転送命令
10-6 ……論理演算命令
10-7 ……分岐命令
10-8 ……ストリング命令
10-9 ……ストリング.プリフイックス命令
10-10 ……フラグ制御命令
10-11 …… CPU 制御命令
10-12 ……セグメント.オーバーライド命令
222
(1) ニモニックのオペランドで使われている記号の意味
オペランド
意味
reg
8 または 16 ビットの汎用レジスタ
reg 8
8ビットの汎用レジスタ
reg 16
16ビットの汎用レジスタ
mem
8または16ビット•メモリロケーション
mem 8
8ビット•メモリロケーシヨン
mem 16
16ビット•メモリロケーシヨン
mem 32
32ビット•メモリロケーシヨン
acc
AX 、 AL レジスタ
sreg
セグメントレジスタ
imm
8ビットまたは16ビットの数値
imm 8
8ビットの数値
imm 16
16ビットの数値
nearproc
現在の命令が置かれているコードセグメント内のプロシージャ
farproc
別のコードセグメント内のプロシージャ
nlabel
命令が置かれているコードセグメント内のラベル
flabel
別のコードセグメント内のラベル
slabel
命令の終わりから一128〜+ 127バイトの範囲のラベル
memptr 16
制御が移されようとしているオフセットが格納してあるワード
memptr 32
制御が移されようとしているオフセットとセグメントが格納して
あるダブルワード
regptr 16
制御が移されようとしているオフセットが格納してあるレジスタ
pvalue
スタックから POP されるバイト数(偶数)
exop
コプロセッサの命令中にエンコードされる数値 (0 〜 63)
223
〈2〉 8086 のレジスタ紹介
名前
説明
AX
アキュムレータ (16 ビット)
AL
AX の下位8ビット(アキュムレータ8ビット)
AH
AX の上位8ビット
BX
ベース•レジスタ (16 ビット)
BL
BX の下位8ビット
BH
BX の上位8ビット
CX
カウンタレジスタ (16 ビット)
CL
CX の下位8ビット
CH
CX の上位8ビット
DX
データ.レジスタ (16 ビット)
DL
DX の下位8ビット
DH
DX の上位8ビット
SI
ソース • インデックス.レジスタ (16 ビット)
DI
ディスティネーション.インデックス.レジスタ (16 ビット)
CS
コードセグメント • レジスタ (16 ビット)
DS
デ'ータセグメント•レジスタ (16 ビット)
ES
ェクストラセグメント•レジスタ (16 ビット)
SS
スタックセグメント.レジスタ (16 ビット)
SP
スタックポインタ (16 ビット)
BP
ベースポインタ (16 ビット)
IP
インストラクションポインタ (16 ビット)
F
フラグ.レジスタ (16 ビット)
<3> フラグ記号の意味
.
変化なし
7
不定
X
結果に従って変化する
0
リセット
1
セット
r
退避した値をストアする
224
<4> フラグの名称
AF
補助キャリーフラグ
DF
デイレクションフラグ
CF
キャリーフラグ
IF
インターラプトフラグ
PF
ノ、。リティーフラグ
OF
オーバーフローフラグ
SF
サインフラグ
TF
トラップフラグ
ZF
ゼロフラグ
(5) クロック記号の意味
記号
意味
N
N 回かけあわせる
/
A/B (A または B)
—
A-B (A から B)
+ EA
•ダイレクト16ビット•オフセット•アドレス (6)
•ベースまたはインデックス•レジスタによるインダイレクト (5)
•インデックス.レジスタとベース•レジスタとの和によるインダイ
レクト (7 or 8)
•ディ スプレイスメントを伴ったベースまたはインデックス • レジス
夕によるインダイレクト ( 9)
•ディ スプレイスメントを伴ったインデックス.レジスタとベース •
レジスタとの和によるインダイレクト (11 or 12)
(注)奇数アドレスに対しては4クロックカロえる。またセグメント •
オーバーライドにはさらに2クロック加える
225
<6)オペレーシヨンコード • フイールド
名前
説明
W
ワード/バイト•フイ ー ルド (0 or 1)
reg
レジスタ•フィールド(〇〇〇〜111)
sreg
セグメント•レジスタ.フィールド(〇〇〜 11)
r/m
レジスタ/メモリ•フィールド(〇〇〇〜111)
mod
モード.フイールド (00 〜 10)
S:W
S : W =01 のとき data = 16 ビット、それ以外は data = 8 ビット
S : W =11 のときバイトデータのサインが拡張されて16ビット •
オペランドを作る
XXX
ESC オペ レー シヨン コー ドのは じめ の3ビット
YYY
ESC オペレーシヨンコードの2番目の3ビット
〈 7 > 8または16ビツト汎用レジスタの選択
氺
reg or r/m
w=o
W =1
000
AL
AX
001
CL
CX
010
DL
DX
011
BL
BX
100
AH
SP
101
CH
BP
no
DH
SI
111
BH
DI
* r / m は mod のない場合
226
〈8> セグメント • レジスタの選択
sreg
内容
00
ES
01
CS
10
SS
11
DS
(9> メモリ.アドレツシンク
\ mod
00
01
10
r / m X
000
BX + SI
BX + SI + disp 8
BX + SI+disp 16
001
BX+DI
BX + DI + disp 8
BX + DI+disp 16
010
BP+SI
BP+SI + disp 8
BP + SI + disp 16
011
BP+DI
BP + DI + disp 8
BP + DI-hdisp 16
100
SI
SI + disp 8
Sl+disp 16
101
DI
Dl+disp 8
Dl+disp 16
110
DIRECT ADDRESS
BP + disp 8
BP + disp 16
111
BX
_
BX + disp 8
BX + disp 16
227
11 reg r/m
mod reg r/m
mod reg r/m
110 0 0 r/m
mod 0 0 0 r/m
ADC
reg,reg
mem, reg
reg, mem
reg,
mem,
acc.
mm
mm
mm
ADD
reg, reg
mem, reg
reg, mem
reg,
mem,
acc.
mm
mm
mm
INC
reg 8
mem
reg 16
FE
11111110
1111111 W
01000 reg
110 0 0
mod 0 0 0
r/m
r/m
DAA
27
0 010 0111
<10〉 8086 ニモニックー覧表
[10-1] 加算命令(アルファベット順)
ニモニック
オペランド
第1バイト
HEX
7 6 5 4 3 2 1 0
第2バイト
HEX
76543210
AAA
37
0 0110111
WWW WWW
o o1 s s o
mmrnmm
/ ////
r r r r r
eeel1
-d d ,
一 o 0
- m m.
WWW WWW
o o1 s s <
228
バイト数
クロック 数
フラグ
ODISZAPC
内容
1
4
?
. ??x?x
Ascii Adjust for Addition
十進アスキーコード間における加算結果を AL レジスタ
に求めたとして、その補正を行う場合に使われる
【使用例】
MOVAH.OOH : AH — 00 H
MOV AL, 35 H : AL — 35„
ADD AL, 35 H : AL — 6 A„
AAA : AX — 0100,,
2
3
X
•xxxxx
ADd with Carry
2-4
16+EA
X.
•xxxxx
キャリーを含む加算を行う
2-4
9+EA
X.
•xxxxx
3-4
4
X.
•xxxxx
3-6
17+EA
x«
. xxxxx
【使用例】
2-3
4
x
. xxxxx
ADC AX.BX : AX—AX + BX+CF
2
3
X.
. • xxxxx
ADDition 加算命令
2-4
16 + EA
X'
.• xxxxx
2-4
9 + EA
X
•• xxxxx
3-4
4
X
, .xxxxx
3-6
17 + EA
X
•• xxxxx
【使用例】
2-3
4
X
.•xxxxx
ADD AX.BX : AX—AX + BX
1
4
?
.• xxxxx
Decimal Adjust for Addition
二進化十進数における加算結果をレジスタ AL に求めた
として、その補正をする
【使用例】
MOV AL.35H : AL— 35„
ADD AL,35 H : AL— 6 A H
DAA : AL— 70 h
2
3
X
•-xxxx-
INCrement by 1
2-4
15+EA
X
•-xxxx-
オペランドの内容を +1 する
1
2
X
•-xxxx-
【使用例】
INC AX
229
[10-2] 減算命令
ニモニック
オペランド
第 i バイト
第 2 パ イト
HEX
76543210
HEX
7 6 5 4 3 2 1 0
AAS
3F
0 0111111
CMP
reg.reg
0 01110 0 W
11 reg r/m
mem , reg
0 01110 0 W
mod reg r/m
reg, mem
0 011101 W
mod reg r/m
reg,imm
10 0 0 0 0 SW
11111 r/m
mem,imm
10 0 0 0 0 s w
mod 111 r/m
acc, imm
0 011110 w
DAS
2F
0 0101111
DEC
reg 8
FE
11111110
110 01 r/m
mem
1111111 w
mod 0 01 r/m
reg 16
010 01 reg
NEG
reg
1111011 W
11011 r/m
mem
1111111 W
mod 011 r/m
SBB
reg, reg
0 0 0110 0 w
11 reg r/m
mem, reg
000110 ow
mod reg r/m
reg , mem
0 0 01101 w
mod reg r/m
reg, imm
10 0 0 0 0 s w
11011 r/m
mem, imm
10 0 0 0 0 s w
mod 011 r/m
acc, imm
0 0 01110 w
SUB
reg, reg
0 01010 0 w
11 reg r/m
mem, reg
0 01010 0 w
mod reg r/m
reg, mem
0 010101 w
mod reg r/m
reg, imm
10 0 0 0 0 s w
11101 r/m
mem, imm
10 0 0 0 0 s w
mod 101 r/m
acc, imm
0 010110 w
23 〇
バイト数
クロック数
フラグ
ODISZAPC
内容
1
4
? •• ??X?X
Ascii Adjust for Subtraction
十進アスキーコード間の減算結果を AL レジスタに求め
たとして、その補正をする
【使用例】
MOV AH.10H : AH— 10„
MOV AL, 35 H : AL — 35„
SUB AL, 36 H : AL — 0FF H
AAS : AX—0F09„
2
2-4
2- 4
3- 4
3-6
2-3
3
9 + EA
9+EA
4
10 + EA
4
X.-XXXXX
X ••XXXXX
X .•XXXXX
X ••XXXXX
X ••XXXXX
X••XXXXX
CoMPare destination to source
比較
【使用例】
CMP AX.BX
JNE * * * *
1
4
?..XXXXX
Decimal Adjust for Subtraction
二進化十進数における減算結果をレジスタ AL に求めた
として、その補正をする
【使用例】
MOV AL.35H : AL—35 H
SUB AL.36H : AL—OFF”
DAS : AL— 99„
2
2-4
1
3
15 + EA
2
X- . xxxx .
X. - xxxx *
X- - xxxx *
DECrement by 1
オペランドの内容を一 1 する
【使用例】
DEC AX
2
2-4
3
16+EA
X..XXXXX
X.•XXXXX
NEGate
レジスタやメモリの内容の補数
【使用例】
NEG AX
2
2-4
2- 4
3- 4
3-6
2-3
3
16+EA
9 + EA
4
17 + EA
4
X••XXXXX
X••XXXXX
X••XXXXX
X..XXXXX
X••XXXXX
X•.XXXXX
SuBtract with Borrow
キャリーを含む減算を行う
【使用例】
SBB AX.BX : AX—AX-BX-CF
2
2-4
2- 4
3- 4
3-6
2-3
3
16 + EA
9 + EA
4
17 + EA
4
X• • XXXXX
X •• XXXXX
X-.XXXXX
X •• XXXXX
X •• XXXXX
X •• XXXXX
SUBtraction
減算命令
【使用例】
SUB AX.BX : AX—AX-BX
231
[10-3] 乗算命令
ニモニック
オペランド
第 1 パ イト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
76543210
AAM
D4
1101010 0
0A
0 0 0 01010
IMUL
reg 8
F6
11110110
11101 r/m
mem 8
F6
11110110
mod 101 r/m
reg 16
F7
11110111
11101 r/m
mem lo
F7
11110111
mod 101 r/m
MUL
reg 8
F6
11110110
1110 0 r/m
mem 8
F6
11110110
mod 10 0 r/m
reg 16
F7
11110111
1110 0 r/m
mem lb
F7
11110111
mod 10 0 r/m
232
Integer MULtiplication
符号付きの乗算命令
1 バイトどうしの乗算と 2 ハ•イトどうしの乗算が可能
1 バイト乘算の時には AL レジスタとオペランド間で乗
算が行われる。結果は AL 、 AH に返される。 2 バイト乗
算の時には AX レジスタとオペランド間で乗算か 1 〒われ
る。結果は AX 、 DX に返される
【使用例】 一 2X3 の場合
MOV AL.0FEH : AL ^——2
MOV BL.3 : BL—• +3
IMULBL : AX- ——6
2 80-98
2 — 4 (86-104) +EA
2 128-154
2 - 4 (134-160)+EA
70-77
(76-83)+EA
118-133
(124-139)+EA
MULtiplication unsigned
符号なしの乗算命令
1 バイトどうしの乗算と 2 パイトどうしの乗算が可能
1 バイト乗算の時には AL レジスタとオペランド間で乗
算が ^^ われる。結果は AL 、 AH に返される。 2 八イト乗
算の時には AX レジスタとオペランド間で乗算が行われ
る。結果は AX 、 DX に返される
【使用例】 2X3 の場合
MOV AL,2
: AL
MOV BL,3
: BL
MUL BL
: AX
ベイ ト数
クロック数
フラグ
0DISZAPC
内容
83
•XX?X?
Ascii Adjust for Multiplication
十進アスキーコード間における乗算結果を AL レジスタ
に求めたとして、その補正を行う場合に使われる。乗
算命令にはアスキーコード数どうしの命令は用意され
ていないので、上位 4 ビットはあらかじめ 0 クリアし
ておかなければならない
【動作】
AI-I—AL を 10 で割った商
AL—AL を 10 で割った余り
【使用例】 3X5 を アスキーコー ドで
MOV AL, 33 H
MOV BL, 35 H
AND AL, 0FH
AND BL, 0FH
MUL BL
AAM
OR AX,3030 H
3 のア スキーコード
5 のア スキーコード
AL — 03„
BL — 05„
AL — 0 F,,
AX — 0105„
AX<- 3135,,
X X X X
X X X X
233
[10-4] 除算命令
ニモニック
オペランド
第 1 パ イト
第 2 バイト
HEX
76543210
HEX
76543210
AAD
D5
11010101
0 A
00001010
CBW
98
10011000
CWD
99
10 0110 01
IDIV
reg8
F6
11110110
11111 r/m
mem 8
F6
11110110
mod 111 r/m
reg 16
F7
11110111
11111 r/m
mem 16
F7
11110111
mod 111 r/m
DIV
reg 8
F6
11110110
11110 r/m
mem 8
F6
11110110
mod 110 r/m
reg 16
F7
11110111
11110 r/m
mem 16
F7
11110111
mod 110 r/m
234
バイト数
クロック数
フラグ
ODISZAPC
内容
2
60
? •-XX?X?
Ascii Adjust for Division
除!):を行う時に AX レジスタの補正をする。除算命令に
はアスキーコード数どうしの命令は用意されていない
ので、除算を行う前に演算に適した形に補正しなけれ
ばならない。他の補正命令は演算後に補正するが、こ
の場合は演算前に補正する
【動作】
AL—AHX10 + AL AH— 0
【使用例】 15 + 7 をアスキーコードで実行する
MOV AX.3135H :15 のアスキーコード
MOV BL.37H : 7 のアスキーコード
AND AX.0F0FH : AX — 0105,,
AND BL.0FH : BL — 07„
AAD : AX — 000F„
DIV BL : AX — 0102„
1
2
Convert Byte to Word
AL レジスタの符号を AH レジスタに拡張する
【動作】
AL レジスタの最上位ビットが〇なら AH レジスタを
00 只に、 1 なら AH レジスタを FFH にする
1
5
Convert Word to Doubleword
AX レジスタの符号を DX レジスタに拡張する
【動作】
AX レジスタの最上位ビットが〇なら DX レジスタを
000 0 H に、 1 なら DX レジスタを FFFFH にする
2
2-4
2
2-4
101-112
(107-118)+EA
165-184
(171-190)+EA
?..?????
?..?????
?..?????
? • •?????
Integer Division
符号付き除算命令
8 ビット長の演算に対しては、 AX レジスタに格納され
ている数値を割る対照とし、商を AL レジスタに、余り
を AH レジスタに返す
16 ビット長の演算に対しては、割られる数値の上位が
DX レジスタに、下位は AX レジスタに格納されているも
のとして演算をほどこし、商は AX レジスタに、余りを
DX レジスタに返す
【使用例】 3+( — 2) の場合
MOV AX, 3
MOV BL.FE
IDIV BL
2
2-4
2
2-4
80-90
(86-96) +EA
144-162
(150-168)+EA
? . . ? ? ? 7 ?
?..?????
? ..???? ?
?..?????
Division unsigned
符号なし除筧命令
8 ビット長の演算に対しては、 AX レジスタに格納され
ている数値を割る対象とし、商を AL レジスタに、余り
を AH レジスタに返す
16 ビット長の演算に対しては、割られる数値の上位が
DX レジスタに、下位は AX レジスタに格納されているも
のとして演算をほどこし、商は AX レジスタに、余りを
DX レジスタに返す
【使用例】 3 + 2 の場合
MOV AX, 3
MOV BL,2
DIV BL
235
[10-5] データ転送命令
ニモニック
オペランド
第 1 バイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
IN
acc , imm 8
1110 010 W
acc, DX
1110110 W
LAHF
9 F
10 011111
LDS
reg 16,
C5
110 0 0101
mod reg r/m
mem 32
LEA
reg 16,
8D
10 0 01101
mod reg r/m
mem 16
LES
reg 16,
C4
110 0 010 0
mod reg r/m
mem 32
MOV
reg, reg
10 0 010 0 w
11 reg r/m
mem, reg
10 0 010 0 w
mod reg r/m
reg, mem
10 0 0101 w
mod reg r/m
mem, imm
110 0 011 w
mod 0 0 0 r/m
reg, imm
1011 W reg
acc, mem
1010 0 0 0 w
mem, acc
1010 0 01 w
sreg , regl6
8E
10 0 01110
110 sreg r/m
sreg, mem
8E
10 0 01110
mod 0 sreg r/m
regl6,sreg
8C
10 0 0110 0
110 sreg r/m
mem, sreg
8C
10 0 0110 0
mod 0 sreg r/m
OUT
imm 8, acc
1110 011 w
DX, acc
111011 1W
236
バイ ト数
クロック数
フラグ
ODISZAPC
内 容
2
10
INput
1
8
AL 、 また SAX レジスタに I / O ポートからのデータを代
入する
1
4
Load AH from Flags
フラグレジスタの下位:8ビットを AH レジスタに代入す
る。また AI - I にフラグデータを取り込めば、フラグデー
夕 を一 般的なビットデータとして扱うことが可能。そ
のデータを SAHF 命令でフラグレジスタに返すこともで
きる
2-4
16 + EA
指定したレジスタ Ids レジスタに第2オペランドで指
定したアドレスから順にデ ー タを取り込む
2-4
2 + EA
Load inflective Addres
メモリオペランドによって指定されるオフセット値を
指定したレジスタに代入する
2-4
16 + EA
指 1し 1 ^ 1 レレジスタに第2オペランドで 指
定したアドレスから順にデータを取り込む
2
2
MOVe
2-4
9 + EA
第2オペランドのデータを第1オペランドへ代入する
2-4
8 + EA
3 — 6
10 + EA
2-3
4
3
10
3
10
2
2
2-4
8 +EA
2-4
9 + EA
2
10
OUTput
1
8
I / O ポートに AL レジスタまた SAX レジスタの値を出力
する
237
ニモニック
オペランド
第 1 バイト
節 2 バイト
HEX
7 6 5 4 3 2 1
HEX
7 6 5 4 3 2 1
POP
mem
reg
sreg
8 F
10 0 01111
01011 reg
0 0 0 sreg 111
mod 0 0 0 17 m
POPF
9 D
10 011101
PUSH
mem
reg
sreg
FF
11111111
01010 reg
0 0 0 sreg 110
mod 110 r/m
PUSHF
9 C
10 01110 0
SAHF
9 E
10 011110
XCHG
reg,reg
mem , reg
AX , reg 16
10 0 0 011 W
10 0 0 011 W
10010 reg
11 reg r/m
mod reg r/m
XLAT
D 7
11010111
238
バイト数
クロック数
フラグ
ODISZAPC
内容
2-4
1
1
17 + EA
8
8
POP word off stack
スタックエリアの先頭からデータを取り出しオペラン
ドへ返す
1
8
rrrrrrrr
POP Flags off stack
スタックエリアの先頭からフラグレジスタへデータを
取り込む
2-4
1
1
16 + EA
10
10
PUSH word onto stack
スタ ッ クエリアの先頭にオペランドの内容を書き込む
1
10
PUSH Flags onto stack
スタックエリアの先頭にフラグレジスタの内容を書き
込む
1
4
… XXXXX
Store AH into Flags
フラグレジスタの下位 8 ビットに AH レジスタの値を代
入する
2
2-4
1
4
17 + EA
3
eXCHanGe
第 1 オペランドと第 2 オペランドの内容を交換する
1
11
1 ranslate
BX レジスタに AL レジスタの内容を加算し、この値を才
フセット値とし、セグメントを DS レジスタの値で参照
されるアドレスからデータを取り出し、 AL レジスタに
格納する
【使用例】
MOV BX.1000 H
MOV [BX], 201 OH
MOV AL,1 : AL—1
XLAT : AL— 20 h
239
[10-6] 論理演算命令
ニモニック
オペランド
第 1 バイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
AND
reg.reg
0 010 0 0 0 w
11 reg r/m
mem, reg
0 010 0 0 0 W
mod reg r/m
reg.mem
0 010 0 01 w
mod reg r/m
reg, i mm
10 0 0 0 0 0 W
1110 0 r/m
mem.imm
100000 OW
mod 10 0 r/m
acc,imm
0 010 010 w
NOT
reg
1111011 w
11010 r/m
mem
1111011 w
mod 010 r/m
OR
reg,reg
0 0 0 010 0 w
11 reg r/m
mem, reg
0 0 0 010 0 w
mod reg r/m
reg, mem
0 0 0 0101 w
mod reg r/m
reg, imm
10 0 0 0 0 0 w
110 01 r/m
mem, imm
10 0 0 0 0 0 w
mod 0 01 r/m
acc.imm
0 0 0 0110 w
RCL
reg.l
11010 0 0 w
11010 r/m
mem,1
11010 0 0 w
mod 010 r/m
reg, CL
11010 01 w
11010 r/m
mem, CL
11010 01 w
mod 010 r/m
RCR
reg.l
11010 0 0 w
11011 r/m
mem,1
110100 ow
mod 011 r/m
reg, CL
11010 01 w
11011 r/m
mem, CL
11010 01 w
mod 011 r/m
24〇
Rotate through Carry Right
キャリーと共にメモリまたはレジスタのビットを右へ
冋転させる。回転する回数は 1 または CL レジスタで指
定する
T
C ->
2
2-4
2
15 + EA
8 + 4 N
20 + EA + 4N
2
2-4
2-4
2
15 + EA
8+4 N
20 + EA + 4 N
Rotate through Carry Left
キャリーと共にメモリまたはレジスタのビットを左へ
回転させる。回転する回数は 1 または CL レジスタで指
定する
T
し
バイト数
クロック数
フラグ
0 DISZAPC
内容
2- 4
3- 4
3-6
2-3
16 + EA
9 + EA
4
17+ EA
4
•XX?X0
•xx?xo
•xx?xo
•xx?xo
•xx?xo
•xx?xo
logical AND
第 1 オペランドと第 2 オペランドとの AND をとり、結
果を第 1 オペランドに返す
2-4
3
16 + EA
logical NOT
オペランドの各ピソ
卜の反転を行う
2
2-4
2- 4
3- 4
3-6
2-3
3
16 + EA
9 + EA
4
17 + EA
4
•XX?X0
•xx?xo
•xx?xo
•xx?xo
•xx?xo
•xx?xo
logical OR
第 1 オペランドと第 2 オペランドとの OR をとり、結果
を第 1 オペランドに返す
X X X X
XX??
X X X X
XX??
241
ニモニック
オペランド
第 i バイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
ROL
reg.l
11010 0 0 W
110 0 0 r/m
mem , 1
11010 0 0 W
mod 0 0 0 r/m
reg.CL
11010 01 W
110 0 0 r/m
mem , しし
11010 01 W
mod 0 0 0 r/m
ROR
reg.l
11010 0 0 W
110 01 r/m
mem , 1
11010 0 0 W
mod 0 01 r/m
reg.CL
11010 01 w
110 01 r/m
mem,CL
11010 01 w
mod 0 01 r/m
SAL
reg.l
11010 0 0 w
1110 0 r/m
SHL
mem,1
11010 0 0 w
mod 10 0 r/m
reg, CL
11010 01 w
1110 0 r/m
mem, CL
11010 01 w
mod 10 0 r/m
SAR
reg.l
110100 ow
11111 r/m
mem,l
11010 0 0 w
mod 111 r/m
reg.CL
11010 01 w
11111 r/m
mem, CL
11010 01 w
mod 111 r/m
SHR
reg.l
11010 0 0 w
11101 r/m
mem,l
11010 0 0 w
mod 101 r/m
reg.CL
11010 01 w
11101 r/m
mem, CL
11010 01 w
mod 101 r/m
TEST
reg,reg
10 0 0 010 w
11 reg r/m
mem, reg
10 0 0 010 w
mod reg r/m
reg, imm
1111011 w
110 0 0 r/m
mem, imm
1111011 w
mod 0 0 0 r/m
acc, imm
1010100 w
XOR
reg, reg
0 0110 0 0 w
11 reg r/m
mem, reg
0 0110 0 0 w
mod reg r/m
reg, mem
0 0110 01 w
mod reg r/m
reg, imm
10 0 0 0 0 0 w
11110 r/m
mem, imm
10 0 0 0 0 0 w
mod 110 r/m
acc,imm
0 011010 w
2^2
ROtate Right
オペランドのビットを右へ回転させる。回転する回数
は 1 または CL レジスタで指定
T
— C
Shift Arithmatic Left
SHift logical Left
オペランドのビットを左へシフトする。シフトする数
は 1 または CL レジスタで指定
し
Shift Arithmatic Right
オペランドのビットを右へ算術シフトする。シフトす
る数は 1 または CL レジスタで指定
符号 —- — C
SHift logical Right
オペランドのビットを右へシフトする。シフトする数
は 1 または CL レジスタで指定
-> C
2
2-4
2
2—4
2
15 + EA
8 + 4N
20 + EA + 4N
2
2-4
2-4
2
15+EA
8 + 4 N
20 + EA + 4 N
2 — 4
2-4
15 + EA
8 + 4N
20 + EA + 4 N
2
2-4
2
2-4
2
15+EA
8 + 4 N
20 + EA + 4 N
2
2-4
2
2-4
15 + EA
8 + 4 N
20 十 EA + 4N
ROtate Left
オペランドのビットを左へ回転させる。回転する回数
は 1 または CL レジスタで指定
T
し
3-4
3-6
2-3
3
9 + EA
5
11 + EA
4
•XX7X0
•XX7X0
•XX7X0
•XX?X0
•XX7X0
TEST
第 1 オペランドと第 2 オペランドとの AND をとる力へ
結果はフラグだけに反映される。オペランドは変化し
ない
2-4
2- 4
3- 4
3-6
2-3
3
16+EA
9 + EA
4
17 + EA
•XX7X0
•XX7X0
•XX7X0
•XX?X0
•XX?X0
•XX?X0
logcial exclusive OR
第 1 オペランドと第 2 オペランドとの XOR をとり、結
果を第 1 オペランドに返す
バイト数
クロック数
フラグ
0DISZAPC
内容
X X X X
XX??-
243
[10 _ 7]分岐命令
ニモニック
オペランド
第 1 パ イト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
CALL
nearproc
E8
111010 0 0
regptr 16
FF
11111111
11010 r/m
memptr 16
FF
11111111
mod 010 r/m
farproc
9A
10 011010
memptr 32
FF
11111111
mod Oil r/m
INT
3
CC
110 0110 0
imm 8
CD
110 01101
(ホ 3)
INTO
CE
110 01110
IRET
CF
110 01111
JA
slabel
77
01110111
JNBE
JAE
slabel
73
01110 011
JNB
JB
slabel
72
01110 010
JNAE
JBE
slabel
76
01110110
JNA
JCXZ
slabel
E3
1110 0 011
244
バイト数
クロッ ク版
フラグ
ODISZAPC
内容
3
19
CALL a procedure
2
16
オペランドで示されるプロシージャをコールする
2-4
21 + EA
5
28
2-4
37 + EA
1
52
• . 〇 .
INTerrupt
2
51
内部 割り込み処理を行う時に使われる。セグメント 0
のはじめの〇〜 3FF„ に、ベクタテーブルが用意されて
おり、 ジャンプ 先を番号によって指定す る
1
53/4
••X .
INTerrupt if Overflow
才ーパーフローフラグが 1 ならタイプ 4 の割り込みを
発生させる
1
24
rrrrrrrr
Interrupt RETurn
割り込み処理からの復帰
2
16/4
Jump if Above
Jump if Not Below nor Equal
上ならジャンプする
【動作】
CF=0 AND ZF = 0 でジャンプ
2
16/4
Jump if Above or Equal
Jump if Not Below
上か等しければジャンプする
【動作】
CF = 0 でジャンプ
2
16/4
Jump if Below
Jump if Not Above nor Equal
下ならばジャンプする
【動作】
CF = 1 でジャンプ
2
16/4
Jump ii Below or Equal
Jump if Not Above
下または等しければジャンプする
【動作】
CF = 1 OR ZF=1 でジャンプ
2
18/6
Jump if CX is Zero
cx レジスタが 0 の場合にジャンブする
245
ニモニック
オペランド
第 1 バイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
JE
JZ
slabe]
74
0111010 0
JG
JNLE
slabel
7F
01111111
JGE
JNL
slabel
7D
01111101
JL
JNGE
slabel
7C
0111110 0
JLE
JNG
slabel
7E
01111110
JMP
nlabel
slabel
regptr 16
memptr 16
flabel
memptr 32
E9
EB
FF
FF
EA
FF
111010 01
11101011
11111111
11111111
11101010
11111111
1110 0 r/m
mod 10 0 r/m
mod 101 r/m
JNE
JNZ
slabel
75
01110101
JNO
slabel
71
01110 0 01
JNP
JPO
slabel
7B
01111011
246
バイト数
クロック数
フラグ
ODISZAPC
内容
2
16/4
Jump if Equal
Jump if Zero
等しければジャンプする
【動作】
ZF=1 でジャンプ
2
16/4
Jump it Greater
Jump if Not Less nor Equal
より大であればジャンプする
【動作】
ZF = 0 AND SF = OF でジャンプ
2
16/4
Jump ir Greater or Equal
Jump if Not Less
以上であればジャンプする
【動作】
SF=OF でジャンプ
2
16/4
Jump if Less
Jump if Not Greater nor Equal
よリ小であればジャンプする
【動作】
SF 本 OF でジャンブ
2
16/4
Jump if Less nor Equal
Jump if Not Greater
以下であればジャンプする
【動作】
ZF = 1 OR SF 辛 OF でジャンプ
3
15
Jump
2
15
オペランドで示された場所にジャンプする
2
11
2-4
18 + EA
5
15
2-4
24 + EA
2
16/4
Jump ir Not Equal
Jump if Not Zero
等しくなければジャンプする
【動作】
ZF=0 でジャンプ
2
16/4
Jump ir Not Overfiow
オーバーフローでなければジャンプする
【動作】
OF=0 でジャンプ
2
16/4
Jump if Not Parity
Jump if Parity Odd
パリテイが奇数ならジャンプする
【動作】
PF=0 でジャンプ
247
ニモニック
オペランド
第 1 パ イト
第 2 バイト
HEX
76543210
HEX
76543210
JNS
slabel
79
011110 01
JO
slabel
70
01110 0 0 0
JP
JPE
slabel
7 A
01111010
JS
slabel
78
011110 0 0
LOOP
slabel
E2
1110 0 010
LOOPE
LOOPZ
slabel
slabel
El
1110 0 0 01
248
バイト数
クロック数
フラグ
ODISZAPC
内容
2
16/4
Jump it Not Sign
サインフラグが 0 ならジャンブする
【動作】
SF=0 でジャンプ
2
16/4
Jump if Overnow
オーバーフローであればジャンプする
【動作】
OF = l でジャンプ
2
16/4
Jump if Not Parity
Jump if Parity Odd
パリテイが奇数ならジャンプする
【動作】
PF = 1 でジャンプ
2
16/4
Jump if Sign
サインフラグが 1 ならジャンプする
【動作】
SF=1 でジャンプ
2
17/5
LOOP
CX レジスタから 1 を引いて CX レジスタが 0 でなければ
ルーブする
( フラグには影嚮を与えない)
【動作】
CX=CX-1
CX 辛 0 であればジャンプする
【使用例】 10 から 1 までの和
MOV BX.0
MOV CX.OAH
LABEL1 : ADD BX,CX
LOOP LABEL1
2
18/6
LOOP if Equal
LOOP if Zero
CX レジスタから 1 を 引いて CX レジスタが 0 でないか、
ゼロ フラグが 1 ならば ルー ブする
( フラグには影髁を与えない)
【動作】
CX = CX-1 ZF = 1 または CX 本 0 でループ
【使用例】
ここでは、 DS: 100 H ~DS:1FF „ までのメモリの内容
で、 0 でないものを見つけたら抜け出すような例を
示す
MOV DI.0FFH
MOV CX , 10 OH
LABEL1 : INC DI
CMP BYTE PTR [DI],0
LOOPE LABEL 1
249
ニモニック
オペランド
第 1 パイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
LOOPNE
slabel
EO
1110 0 0 0 0
LOOPNZ
slabel
RET (near)
C3
110 0 0 011
(far)
CB
110 01011
RET (near)
pvalue
C2
110 0 0 010
(far)
(偶数)
CA
110 01010
25〇
バイ ト数
クロック 数
フラグ
ODISZAPC
内容
2
19/5
LOOP if Not Equal
LOOP if Not Zero
CX レジスタから 1 を引いて CX レジスタが 0 でないか、
ゼロフラグが〇ならばループする
( フラグには影響を与えない)
【動作】
CX=CX-1 ZF=0 または CX 本 0 でループ
【使用例】
ここでは、 DS:100„~DS:1FF H までのメモリの内容
で、 0 を見つけたら抜け出すような例を示す
MOV DI.0FFH
MOV CX , 10 OH
LABEL 1:INC DI
CMP BYTE PTR [DI],0
LOOPNE LABEL 1
1
8
RETurn from procedure
1
18
プロシージャからの復帰
3
12
RETurn from procedure
3
17
プロシージャから復帰し、スタックポインタに pvalue
値を加算する
251
[10-8] ストリング命令
ニモニック
オペランド
第 1 バイト
第 2 バイト
HEX
76543210
HEX
7 6 5 4 3 2 1 0
CMPSB
A6
1010 0110
CMPSW
A7
1010 0111
LODSB
AC
1010110 0
LODSW
AD
10101101
252
バイト数
クロック数
フラグ
ODISZAPC
内容
1
22 OR 9 + 22 N
X••XXXXX
CoMPare String for Byte
1
22 OR 9 + 22 N
X••XXXXX
CoMPare String for Word
セグメント DS レジスタ、オフセツト SI レジスタで示さ
れるメモリの内容と、セグメント ES レジスタ、オフセツ
卜 DI レジスタで示されるメモリの内容を八イト(ワー
ド)単位で比較する
SI 、 DI レジスタの値はこの命令の実行後 、 DF = 0 であ
れば +1( + 2)、 DF = 1 であれば一 1 ( — 2 ) だけ更新さ
れる
REPZ 、 REPNZ などと組合せてブロツク比較が可能。こ
の時の繰返し数は CX レジスタの値が使われる。 CX レジ
スタは自動的に更新され XX=0 か REPZ や REPNZ での条
件が成り立てば実行が終了となる
1
12 OR 9 + 13 N
LOaD String for Byte
1
12 OR 9 + 13 N
LOaD String for Word
セグメント DS レジスタ、オフセツト SI レジスタで示さ
れるメモリの内容を、ハ • イト単位であれば AL レジスタ
に、ワード ( 2 バイト)単位であれば AX レジスタに
口ードする
SI レジスタの値はこの命令の実行後 、 DF = 0 で
あれば +1( + 2)、 DF = 1 であれば一 1( — 2 ) だけ更新さ
れる
REP 命令と組合せて連続動作が可能となる。この時の
繰返し数は CX レジスタの個 ^( 使われる。 CX レジスタは
自動的に更新され 、 CX = 0 になれば実行が終了となる
253
ニモニック
オペランド
第 1 ハ M 卜
第 2 パ イト
HEX
7 6 5 4 3 2 1 0
HEX
76543210
MOVSB
A 4
1010 010 0
MOVSW
A5
1010 0101
SCASB
AE
10101110
SCASW
AF
10101111
STOSB
AA
10101010
STOSW
AB
10101011
254
バイト数
クロック数
フラグ
ODISZAPC
内 容
1
18 OR 9 + 17 N
MOVe String for Byte
1
18 OR 9 + 17 N
MOVe String for Word
セグメント DS レジスタ、オフセツト SI レジスタで示さ
れるメモリの内容を、セグメント ES レジスタ、オフセツ
卜 DI レジスタで示されるメモリの内容へバイト(ワー
ド)単位で転送する
SI 、 DI レジスタの値はこの命令の実行後 、 DF = 0 であ
れば+1(+2 )、 DF = 1 であれば 一 1(一 2) だけ更新さ
れる
REP 命令と組合せて連続動作が可能となる。この時の
繰返し数は CX レジスタの値が使われる。 CX レジスタは
自動的に更新され 、 CX = 0 になれば実行が終了となる
1
15 OR 9 + 15 N
X••XXXXX
SCAn String for Byte
1
15 OR 9 + 15 N
X- - XXXXX
SCAn String for Word
セグメント ES レジスタ、オフセツト DI レジスタで示さ
れるメモリの内容と、バイト単位であれば AL レジスタ、
ワード ( 2 バイト)単位であれば AX レジスタの値との
比較を行う
DI レジスタの値はこの命令の実行後、 DF 二 0 で
あれば十 1( 十 2 )、 DF =1 であれば一 1( 一 2 ) だけ更新さ
れる
REPZ 、 REPNZ などと組合 ^ て連続比 ^ が可能となる。
この時の繰返し数は CX レジスタの値が使われる。 CX レ
ジスタは自動的に更新され XX=0 か REPZ や REPNZ での
条件が成り立てば、実行が終了となる
1
11OR 9 + 10 N
STOre String for Byte
1
11OR 9 + 10 N
STOre String for Word
セグメント ES レジスタ、オフセツト DI レジスタで示さ
れるメモリの内容を、バイト単位であれば AL レジスタ、
ワード ( 2 バイト)単位であれば AX レジスタの内容に
書き換える
DI レジスタの値はこの命令の実行後 、 DF = 0 で
あれば +1( + 2)、 DF = 1 であれば一 1( — 2 ) だけ更新さ
れる
REP 命令と組合わせて連続動作が可能。繰返し数は CX
レジスタの値が使われる。 CX レジスタは自動的に更新
され 、 CX = 0 になれば実行が終了となる
255
[10-9] ストリング•プリフィックス命令
ニモニック
オペランド
第 1 バイト
第 2 ハ ♦イト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
REP
REPE
REPZ
F3
11110 011
REPNE
REPNZ
F2
11110 010
[10-10] フラグ制御命令
ニモニック
オペランド
第 1 バイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
CLC
F8
11111000
CLD
FC
1111110 0
CLI
FA
11111010
CMC
F5
11110101
STC
F9
11111001
STD
FD
11111101
STI
FB
11111011
256
バイト数
クロック数
フラグ
ODISZAPC
内容
1
2
Repeat while CX 本 0
Repeat while CX 羊 0 & ZF = 1
Repeat while CX^O & ZF = 1
ストリング命令の前に置き、次のストリング命令を、
CX 辛 0 か ZF = 1 となっている間実行する
REP 、 REPE 、 REPZ はいずれも同じマシン語コードであ
り、 1 回の指定のみ有効となっている
1
2
Repeat while CX^O & ZF = 0
Repeat while CX 辛 0 & ZF = 0
ストリング命令の前に置き、次のストリング命令を、
CX 辛 0 か ZF=0 となっている間実行する
REPNEXREPNZ はいずれも同じマシン語コードであり、
1 回の指定のみ有効となっている
バイト数
クロック数
フラグ
ODISZAPC
内容
1
2
. 0
CLear Carry flage
キャリーフラグをクリア CF=0
1
2
• 〇 .
CLear Direction flage
ディ レクシヨンフラグをクリア DF = 0
1
2
• • 〇 .
CLear Interrupt flage
割り込みフラグをクリア IF = 0
1
2
. X
CoMplement Carry flage 一
キャリーフラグの反転を行う CF = CF
1
2
. 1
SeT Carry flage
キャリーフラグをセツトする CF =1
1
2
• 1 .
SeT Direction flage
ディ レクシヨンフラグをセットする DF = 1
1
2
..…
SeT Interrupt flage
割り込みフラグをセットする IF=1
257
[10-11] CPU 制御命令
ニモニック
オペランド
第 i バイト
第 2 八 イト
HEX
7 6 5 4 3 2 1 0
HEX
7 6 5 4 3 2 1 0
ESC
exop,reg
exop, mem
11011 XXX
11011 XXX
11YYY r/m
mod YY Y r/m
HLT
F4
11110100
LOCK
FO
11110 0 0 0
NOP
90
10 010 0 0 0
WAIT
9B
10 011011
[10~12]セクメント•才ーバーライド命令
ニモニック
オペランド
第 1 バイト
第 2 バイト
HEX
7 6 5 4 3 2 1 0
HEX
76543210
CS:
2E
0 0101110
DS:
3E
0 0111110
ES:
26
0 010 0110
SS:
36
0 0110110
258
バイト数
クロック数
フラグ
ODISZAPC
内容
2
2
8 + EA
データバスにオペラン ドで指定したメモリの内容を設
定する
2 — 4
HaLT
CPU の実行停止命令
1
2
LOCK bus
パスのロッ ク 信号を 設定する
1
2
No OPeration
何も実行しない命令
1
3
3 + 5N
Wai—
1
test ピンの 信号がアクティブになるまでウェイトする
バイト数
クロック数
フラグ
ODISZAPC
内容
1
2
セグメントの参照を CS レジスタとする
1
2
セグメントの参照を DS レジスタとする
1
2
セグメントの参照を ES レジスタとする
1
2
セグメントの参照を SS レジスタとする
259
ア入 -\■•ーコードー覧表
上位4ビット―
o
1
~2
~4
5~
互
7 i
l 9
A
互
~c
~〇
I
~F
0
D
E
fSPl
0
@
p
i
P ■
L
一
T
T
===
X
1
s
H
D
1
I
i
~A
~Q
a
q ■
■IT
o
~T
~¥
~A
—
円
2
S
X
D
2
//
2
~B~
R
~b~
r _
厂
T
~7
二
:一
互
r
■t 一
—
—
干
3
E
X
D
3
T"
I
"c~
S
c
is
t
■ j
モ
g|
T
4
E
T
D
4
$
T
~d"
T
~d~
is
\
エ
T
王
日
5
E
Q
N
K
%
T
~E~
U
e
•
T
ユ
W
6i
A
K
S
N
&
T
F
V
T
V
it
ヲ
- 二 —
k.
¥
7
B
し
E
B
/
T
G
W
g
w
c
ァ
A
更
8
B
S
C
N
T
T
H
X
h
X
r
■ィ
王
T
□
—
9
H
T
E
M
丄
T
1
Y
i
y
n
ヴ
7
ル
□
A
し
F
S
B
*
•
J
Z
j
z
i:
_エ
=1
ハ
V
□
b"
H
M
E
C
"T
>
K
n
:
k
I
J
才
V
□
□
~C
C
し
— >
T
¥
T
1
1
r
ャ
~V
□
~D
C
R
< —
—
M
D
m
[
ZL
ス
へ
B
~E
S
0
个
•
A
门
1 V
_ 3
~¥
ホ
\、
■
If
1
i
7
~T
~0
_
0
—
ーノ
ッ
V
マ
0
fil
(>i)[SPl は空白(スペース)コードを示します
下&4ビツ.^ -- >
26 〇
この『8086マシン語秘伝の書』をまとめるにあたり、以下の文献にお世話にな
りました。この場をかりてお礼を申しあげます。
♦本文
r ザ8086ブック』吉川敏則訳
『 PC -9801 マシン語入門』岩瀬正幸 • 藤井敬雄共著
『はじめて読む MASM 』 蒲地輝尚著
『 MS - DOS プログラミングテクニック』
アスキー 書籍編集部編著
『8086アセンブリ言語 J 西村義考著
『8086プロダラミングデザイン』 山 内直著
『 FORTRAN のための数値計算法』村越勝弘訳
『マシン語クックブック1』藤田英時 • 幸田敏記共著
『 PC - 9800はじめてのマシン語』日高徹 •青山 学共著
産報出版
アスキー
アスキー
アスキー
日本ソフトバンク
秀和システムトレーデイング
科学技術出版社
システムソフト
啓学出版
♦ニモニック表
『ザ8086ブック J 吉川敏則訳
『 PC -9801 マシン語入門』岩瀬正幸 • 藤井敬雄共著
『8086アセンブリ言語 J 西村義考著
『8086プログラミングデザイン』山内直著
産報出版
アスキー
日本ソフトバンク
秀和システムトレーデイング
261
1990年 10 月 31 日第1刷発行
1991年5月31日第2刷発行
発行所啓学出版株式会社
代表者三井数美
郵便番号101
東京都千代田区神田神保町 1-46
電話東京 03(3233)3731 [編集部]
東京 03(3233)3795 [販売部]
振替東京 3-109286
印刷/昭和工業写真印刷所
製本/徳住製本所
ISBN 4-7665-1079-8 本書の定価は カバーに 表示してあります
< 著者紹介 >
日高徹
1949年栃木県宇都宮市生まれ
早稲田大学商学部卒業後、商社やカー用品メーカーに十数年勤務。現在はフリーのゲームデザイナー。
主な作品は、『ホーンテッドケイブ j r マジックガーデン j r ガンダーラ j など。著書に r マシン語ゲー
ムプロダラミング J rPC-8801 シリーズマシン語サウンド•プログラミング J (以上アスキー) rPC-8801
シリーズマシン語ゲームグラフィックス J (小学館) rPC-8800 シリーズはじめてのマシン語 J『PC
-9800 シリーズはじめてのマシン語 J 『 Z80 マシン語秘伝の書 J (以上啓学出版)がある。
趣味はトレーニング。剣道三段。運転免許証を全種類もつ隠れプロドライバーでもある0
青山学
1958年東京生まれ
青山学院大学理工学部卒業後、コンピュータエンジニアを経て、現在はフリーのゲームデザイナー0
主な作品は、 98 版 r ゼビウス J 、 88 版『ドラゴンバスター J など。
趣味はスキー、テニス。
[編集部からのお願い]
本書の内容に関する質問等は書面にて当
編集部宛へお送り願います。電話による
質問等にはいっさい応じられません。
8086 マシン語秘伝の書 © Hidaka.T/Aoyama.M 1990
¥真子
• S 问2山
ひ日仙青
者
著
Printed in japan
1 suchi
卿 I マシン疆麵書
i 孛出版
(出)1353
■六好評/日高礅•青山学のマシン語の本
•なにごとにも最初が肝心-
PC - 8800シリーズ
はじめてのマシン語
日高徹著
A 5判172頁定価1960円
• まずモニタでやってみよう -
PC - 9800シリーズ
はじめてのマシン言吾
日高徹 • 青山学著
A 5判172頁定価2000円
•マシン語の極意 M 云授一
Z 80マシン語秘伝の書
日高徹著
A 5判230頁定価1800円
ISBN 4」7665 -1079-8 C 3055 P 200 0 E
定価2,000円(本体1,942円)
咖 i マシン B 鼸繾