リピートプリフィックス


連続したストリング操作

前回、ストリング操作の基本的な役割と動作を説明しました
今回は、ストリング操作命令と組み合わせて用いる特殊な命令を紹介します

ストリング操作命令とLOOPを用いることで、大量のデータの転送を行うことができます
しかし、さらにこれらの動作を一括して行うことができるリピートプリフィックスというものがあります

ストリング操作命令の前にリピートプリフィックスを付加することで
特定の条件を満たしている愛だ、ストリング操作命令を繰り返し実行します
リピートプリフィックスには次のものが用意されています

リピートプリフィックス動作終了条件
REP 通常のリピート CX = 0
REPE 等しければリピート CX = 0 または ZF = 0
REPZ ゼロであればリピート CX = 0 または ZF = 0
REPNE 等しくなければリピート CX = 0 または ZF = 1
REPZE ゼロでなければリピート CX = 0 または ZF = 1

すでに気づいていると思いますが、REPE/REPZ , REPNE/REPZE はそれぞれ同じです
例えば、REPE も REPZ も機械語に訳すと F3 となります

REP 以外のリピートプリフィックスを MOVSB に使うことはまずありません
これらは、後ほど紹介する検索などのストリング操作に用いられます

終了条件の一つとして CX レジスタが0必要がありますが
全てのリピートプリフィックスは繰り返すたびにCXレジスタをデクリメントします
つまり、REPであればCXレジスタにセットされている回数だけストリング操作命令を繰り返すということです

リピートプリフィックスは、その名のとおりストリング操作命令の前に付加します
例として、次のような形になります

REP MOVSB

必ず、リピートプリフィックスは1つのストリング操作命令だけに適応されます
これはあくまで、ストリング操作のための命令であり
一連の構造を繰り返すには LOOP 命令を使う必要があります

では、さっそく特定の文字列のデータ転送を行ってみましょう
DEBUG の E コマンドはリストに文字列を指定することもできます
今回は、最初に E コマンドでメモリに文字列を配置し、それを転送させてみましょう
-E 200 "Kitty on your lap"
-A 100
15F2:0100 MOV SI , 200
15F2:0103 MOV DI , 300
15F2:0106 MOV CX , 11
15F2:0109 CLD
15F2:010A REP MOVSB
15F2:010C
-G =100 10C

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0211  DI=0311
DS=15F2  ES=15F2  SS=15F2  CS=15F2  IP=010C   NV UP EI PL NZ NA PO NC

-D 200 210
15F2:0200  4B 69 74 74 79 20 6F 6E-20 79 6F 75 72 20 6C 61   Kitty on your la
15F2:0210  70                                                p
-D 300 310
15F2:0300  4B 69 74 74 79 20 6F 6E-20 79 6F 75 72 20 6C 61   Kitty on your la
15F2:0310  70                                                p
文字列の個数だけ CX レジスタにセットし、その回数だけストリング操作命令で転送しています
ストリング操作命令は、実行されるごとにポインタをインクリメントしているので
結果として次のように、文字列を丸々転送した形になります


デクリメントの必要性

ところで、ストリング操作命令は実行するごとにポインタをデクリメントすることもできました
実際に考えると、あまり実用性がない気がしてきますね

しかし、ある特定の条件の中での転送ではこれが必要になります
その代表例が、転送する領域の一部が同じ空間を共有している場合です

転送元のデータ 共有空間 転送先のデータ

つまり、転送もとのデータの末尾部分が転送先のデータの開始アドレスとなる場合です
これをインクリメントで行うと、見るも無残な結果に終わります
-E 200 "Kitty on your lap"
-A 100
15F2:0100 MOV SI , 200
15F2:0103 MOV DI , 205
15F2:0106 MOV CX , 11
15F2:0109 CLD
15F2:010A REP MOVSB
15F2:010C

-G =100 10C

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0211  DI=0216
DS=15F2  ES=15F2  SS=15F2  CS=15F2  IP=010C   NV UP EI PL NZ NA PO NC

-D 200 215
15F2:0200  4B 69 74 74 79 4B 69 74-74 79 4B 69 74 74 79 4B   KittyKittyKittyK
15F2:0210  69 74 74 79 4B 69                                 ittyKi
どうでしょうか、最初に転送した時点で転送もとのデータが破壊されてしまいます
そのため、正しく文字列を転送できませんでしたね

これを解決するには、データの転送をデータの末尾部分から行う必要があります
つまり、これまでとは逆の方法で転送することでデータを守ることができるのです

末尾部分からデータを転送するには、ポインタをそれぞれの終点にセットし
DFフラグレジスタを STD でセットします
こうすることで、ストリング操作命令は実行ごとにポインタをデクリメントします
-E 200 "Kitty on your lap"
-A 100
15F2:0100 MOV SI , 210
15F2:0103 MOV DI , 215
15F2:0106 MOV CX , 11
15F2:0109 STD
15F2:010A REP MOVSB
15F2:010C
-G =100 10C

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=01FF  DI=0204
DS=15F2  ES=15F2  SS=15F2  CS=15F2  IP=010C   NV DN EI PL NZ NA PO NC
15F2:010C FC            CLD
-D 200 215
15F2:0200  4B 69 74 74 79 4B 69 74-74 79 20 6F 6E 20 79 6F   KittyKitty on yo
15F2:0210  75 72 20 6C 61 70                                 ur lap
オフセットアドレス 200〜210 を 205〜215 まで転送できたことがわかりますね
このような場合には、デクリメントによる転送が有効になります



前のページへ戻る次のページへ