リピートプリフィックス
連続したストリング操作
前回、ストリング操作の基本的な役割と動作を説明しました
今回は、ストリング操作命令と組み合わせて用いる特殊な命令を紹介します
ストリング操作命令と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 まで転送できたことがわかりますね
このような場合には、デクリメントによる転送が有効になります