Skip to main content

Full text of "8086マシン語秘伝の書"

See other formats


的 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 鼸繾