彙編 - 字串
我們已經在之前的示例中使用了變長字串。變長字串可以包含任意數量的字元。通常,我們透過以下兩種方式之一指定字串的長度:
- 顯式儲存字串長度
- 使用哨兵字元
我們可以使用表示當前位置計數器值的 $ 位置計數器符號顯式儲存字串長度。在下面的示例中:
msg db 'Hello, world!',0xa ;our dear string len equ $ - msg ;length of our dear string
$ 指向字串變數 msg 的最後一個字元之後的位元組。因此,$-msg 給出了字串的長度。我們也可以寫
msg db 'Hello, world!',0xa ;our dear string len equ 13 ;length of our dear string
或者,您可以使用尾隨哨兵字元儲存字串以分隔字串,而不是顯式儲存字串長度。哨兵字元應為字串中未出現的特殊字元。
例如:
message DB 'I am loving it!', 0
字串指令
每個字串指令可能需要一個源運算元、一個目標運算元或兩者兼而有之。對於 32 位段,字串指令使用 ESI 和 EDI 暫存器分別指向源和目標運算元。
但是,對於 16 位段,SI 和 DI 暫存器分別用於指向源和目標。
有五條處理字串的基本指令。他們是:
MOVS - 此指令將 1 位元組、字或雙字的資料從一個記憶體位置移動到另一個記憶體位置。
LODS - 此指令從記憶體載入。如果運算元為一個位元組,則將其載入到 AL 暫存器中,如果運算元為一個字,則將其載入到 AX 暫存器中,雙字載入到 EAX 暫存器中。
STOS - 此指令將資料從暫存器 (AL、AX 或 EAX) 儲存到記憶體中。
CMPS - 此指令比較記憶體中的兩個資料項。資料可以是位元組大小、字或雙字。
SCAS - 此指令將暫存器 (AL、AX 或 EAX) 的內容與記憶體中一項的內容進行比較。
上述每條指令都有位元組、字和雙字版本,並且可以透過使用重複字首重複字串指令。
這些指令使用 ES:DI 和 DS:SI 暫存器對,其中 DI 和 SI 暫存器包含有效偏移地址,這些地址引用儲存在記憶體中的位元組。SI 通常與 DS(資料段)相關聯,而 DI 始終與 ES(額外段)相關聯。
DS:SI(或 ESI)和 ES:DI(或 EDI)暫存器分別指向源和目標運算元。源運算元假定位於記憶體中的 DS:SI(或 ESI),目標運算元位於 ES:DI(或 EDI)。
對於 16 位地址,使用 SI 和 DI 暫存器,對於 32 位地址,使用 ESI 和 EDI 暫存器。
下表提供了字串指令的各種版本以及運算元的假設空間。
| 基本指令 | 運算元位於 | 位元組操作 | 字操作 | 雙字操作 |
|---|---|---|---|---|
| MOVS | ES:DI, DS:SI | MOVSB | MOVSW | MOVSD |
| LODS | AX, DS:SI | LODSB | LODSW | LODSD |
| STOS | ES:DI, AX | STOSB | STOSW | STOSD |
| CMPS | DS:SI, ES: DI | CMPSB | CMPSW | CMPSD |
| SCAS | ES:DI, AX | SCASB | SCASW | SCASD |
重複字首
REP 字首在設定字串指令之前(例如 - REP MOVSB)時,會導致根據放置在 CX 暫存器中的計數器重複指令。REP 執行指令,將 CX 減 1,並檢查 CX 是否為零。它重複指令處理,直到 CX 為零。
方向標誌 (DF) 確定操作的方向。
- 使用 CLD(清除方向標誌,DF = 0)使操作從左到右。
- 使用 STD(設定方向標誌,DF = 1)使操作從右到左。
REP 字首還有以下變體
REP:它是無條件重複。它重複操作直到 CX 為零。
REPE 或 REPZ:它是條件重複。它在零標誌指示相等/零時重複操作。當 ZF 指示不相等/零或 CX 為零時停止。
REPNE 或 REPNZ:它也是條件重複。它在零標誌指示不相等/零時重複操作。當 ZF 指示相等/零或 CX 減至零時停止。