ぐだぐだ低レベルプログラミング(208)x86(16bit)、LODSとSTOS

Joseph Halfmoon

前回はストリング命令SCASとCMPSを練習しました。どちらもREPプリフィックスでCX回繰り返し、途中ゼロフラグで継続か中断する判断するのに向いてます。しかしストリング命令と括られる中にはREPプリフィックスと「相性」の良くない命令があります。LODSとSTOSです。でもこいつら意外と便利なんだ、ホントか?

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

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

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

LODSは、DS:SIで指定されるメモリからAL(バイト)またはAX(ワード)レジスタにメモリ上の値をロードする命令です。実行後、DF(ディレクション・フラグ)の指定に従いSIの値が転送幅に応じて更新されます。転送先はキメウチのレジスタなのでこれにREPプリフィックスを付加して繰り返しても有意義とは思えませぬ(時間つぶしだけ?)しかし、x86系のメモリアドレシングにはスタック操作を除くと自動インクリメント/デクリメント系のアドレシングが欠けてます。そこにLODS使う意義があるみたいです。

一方STOSは、ES:DIで指定されるメモリへAL(バイト)またはAX(ワード)の内容を転送する命令です。こちらも、実行後、DFの指定に従いDIの値が転送幅に応じて更新されます。STOSの場合、メモリフィル操作のようなケースでは、REPプリフィックスを使って繰り返す意義がある、というものです。しかしそれ以外ではREP無で、自動インクリメント/デクリメント系のアドレシングを使うための命令とみた方が良い感じです。

今回実験のプログラム

強力なx86用アセンブラNASM用のソースです。メモリにおいた “Hello worldza”復帰改行というソース文字列中の英小文字のみを大文字に変換してデスティネーション文字列として書きこむもの。末尾のzaはテスト用です。変換前と変換後でMS-DOSのファンクション0x09を使い2つの文字列を印字してます。小文字以外は何もせずに転送するだけなので、変換後は全英大文字の文字列が印字される筈。

segment code

..start:
    mov ax, data
    mov ds, ax
    mov es, ax
    mov ax, stack
    mov ss, ax
    mov sp, stacktop
beforet:
    mov dx, srcblk
    mov ax, 0x0900
    int 0x21
    mov dx, dstblk
    mov ax, 0x0900
    int 0x21
    mov si, srcblk
    mov di, dstblk
test:
    lodsb
    cmp al, '$'
    jz aftert
    cmp al, 'a'
    jae lbla
    jmp next
lbla:
    cmp al, 'z'
    ja  next
    sub al, 'a' - 'A'
next:
    stosb
    jmp test
aftert:
    stosb
    mov dx, srcblk
    mov ax, 0x0900
    int 0x21
    mov dx, dstblk
    mov ax, 0x0900
    int 0x21
fin:
    mov ax, 0x4c00
    int 0x21
    resb    2048

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

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

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

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

今回はいつもと異なり、デバッガを使わず、MS-DOSのシステムコールで文字列を画面に印字して、動作を確認しています。

結果が以下に。LODS_STOS

一番上が、変換実行前のソース文字列。2番目が転送前のデスティネーション文字列、最初はピリオドが詰まっております。そして3番目が変換後のソース文字列、当然、さきほどと同じ。最後4番目が変換後のデスティネーション文字列です。全部大文字になっとります。

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

コメントを残す

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