ぐだぐだ低レベルプログラミング(207)x86(16bit)、SCASとCMPS

Joseph Halfmoon

x86(16bit)のオペコードマップの「塗りつぶし」も見た目は後一息という雰囲気を醸してます。今回は過去回でMOVSのみ練習して他の命令どもから目を背けていたストリング命令の残りからSCASとCMPSを練習してみます。メモリの中から特定のパターンを見つけたり文字列同士の比較に威力を発揮するもの。まあCISCらしい。

※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら

※実機動作確認(といってもエミュレータなんだけれども)には以下を使用させていただいております。

    •  Windows 11 PC (i5-1235U)
    •  Ubuntu 24.04 LTS on WSL2
    •  QEMU 8.2.2
    •  FreeDOS 1.3
SCASとCMPS

SCASは、バイトの場合AL、ワードの場合AXレジスタに値を入れ、ES:DIにメモリアドレスを、CXに調べる回数をロードして呼び出すとメモリを「舐めて」一致、不一致を調べてくれる命令です。プリフィックスREPZを付加すれば比較結果が一致しているかCXが0でない間同じ動作を繰り返し、REPNZを付加すれば比較結果が一致しないかCXが0でない間繰り返します。勿論、アドレスの更新方向はFlagsのDF(ディレクション・フラグ)によって決定されます。ちょいメンドイけど便利ね~。

CMPSは、DS:SIに第1のメモリアドレスをES:DIに第2のメモリアドレスを入れ、CXに比較回数をロードして呼び出すとメモリ同士を比較して、一致、不一致を調べてくれる命令です。プリフィックスREPZを付加すれば比較結果が一致しているかCXが0でない間同じ動作を繰り返し、REPNZを付加すれば比較結果が一致しないかCXが0でない間繰り返します。やはりアドレスの更新方向はFlagsのDF(ディレクション・フラグ)によって決定されます。

なお、REPZをREPEと綴ってもよいし、REPNZをREPNEと綴るのもありです。

今回実験のプログラム

強力なx86用アセンブラNASM用のソースです。メモリにおいた “Hello world.”復帰改行と”Hello World.”復帰改行を使って通り一遍の比較を行うだけのもの。

segment code

..start:
    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax
    mov sp, stacktop
    mov ax, edata
    mov es, ax
test1:
    mov di, dstblk
    mov al, 'W'
    mov cx, 15
    cld
    repnz scasb
test2:
    mov si, srcblk
    mov di, dstblk
    mov cx, 15
    cld
    repz cmpsb
fin:
    mov ax, 0x4c00
    int 0x21
    resb    2048

segment data    align=16
    resb    1024 * 63
srcblk: db  'Hello world.',13,10,'$',0

segment edata   align=16
    resb    1024 * 63
dstblk: db  'Hello World.',13,10,'$',0

segment stack   class=STACK align=16
    resb    2048
stacktop:
    dw 1024 dup (0)
stackend:
アセンブルして実行

MS-DOS互換で機能強化されてるフリーなFreeDOS上、以下のステップで上記のアセンブラソース scas.asm から実行可能なオブジェクトファイルを生成して実行することができます(nasmとwatcom Cがインストール済であること。)

nasm -f obj -l scas.lst scas.asm 
wlink name scas.exe format dos file scas.obj
debug scas.exe

デバッガ起動後、今回のプログラムの逆アセンブルを行ったところ。SCASunassemble

この一命令にて、whileループ1個分の働きがあると思えば強力。

メモリ上に配置したテストデータの様子が以下に。SCASsrc

上がDS:SIでポイントする方、下がES:DIでポイントする方です。7文字目のwが上は小文字、下は大文字であることをご確認くだされや。

さて以下はES:DIに対して大文字 ‘W’ をみつけるためのSCASを発行したときのもの。なお、SCASを含むストリング命令群は全てREPの途中で割り込みを受け付けるので、「トレース」すると一周毎に止まってくれます。SCAS0

上記を見るとDIがFC07のところで大文字Wを発見してREPの繰り返しを脱出してきたことが分かります。

お次はCMPS、DS:SIとES:DIを比較するもの。当然7文字目が w と W で差異があるので、そこが不一致になる筈。CMPS0

予定通りの挙動ぞなもし。

ぐだぐだ低レベルプログラミング(206)x86(16bit)、XLAT へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です