最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

5.3 匯編語言:字符串操作指令

2023-08-23 09:57 作者:bili_42682284418  | 我要投稿

本章將深入研究字符串操作指令,這些指令在匯編語言中具有重要作用,用于處理字符串數(shù)據(jù)。我們將重點介紹幾個關鍵的字符串操作指令,并詳細解釋它們的功能和用法。通過清晰的操作示例和代碼解析,讀者將了解如何使用這些指令進行字符串比較、復制、填充等常見操作。我們還將探討不同指令之間的區(qū)別,并提供實際的示例程序,展示字符串操作指令在實際場景中的應用。通過學習本章,讀者將能夠拓展匯編技能,為處理字符串數(shù)據(jù)提供高效而精確的解決方案。


常見的字符串操作指令包括:


?- MOVSB / MOVSW / MOVSX:在兩個存儲器地址之間復制一個字節(jié)、一個字或一個雙字。其中 MOVSB 復制一個字節(jié),MOVSW 復制一個字,MOVSX 復制一個雙字。

?- CMPSB / CMPSW / CMPSD:比較兩個存儲器地址中的一個字節(jié)、一個字或一個雙字,并將比較結(jié)果存儲在條件碼寄存器中。其中 CMPSB 比較一個字節(jié),CMPSW 比較一個字,CMPSD 比較一個雙字。

?- LODSB / LODSW / LODSD:從存儲器中讀取一個字節(jié)、一個字或一個雙字,并將其存儲在累加器中。其中 LODSB 讀取一個字節(jié),LODSW 讀取一個字,LODSD 讀取一個雙字。

?- STOSB / STOSW / STOSD:將一個字節(jié)、一個字或一個雙字寫入存儲器,并將累加器的值相應地更新。其中 STOSB 寫入一個字節(jié),STOSW 寫入一個字,STOSD 寫入一個雙字。

?- SCASB / SCASW / SCASD:在存儲器地址中掃描一個字節(jié)、一個字或一個雙字,并將掃描結(jié)果存儲在條件碼寄存器中。其中 SCASB 掃描一個字節(jié),SCASW 掃描一個字,SCASD 掃描一個雙字。


這些字符串操作指令通常是通過累加器(即 AH、AL、AX 或 EAX 等寄存器)來控制讀取或?qū)懭氲臄?shù)據(jù)大小,同時還需要通過 DF 標志位來控制是向存儲地址增加還是減小。在使用字符串操作指令時,需要仔細理解這些指令的語法和操作方式,以便正確地處理字符串數(shù)據(jù)。


### 3.1 MOVSB/MOVSW/MOVSD


移動串指令包括了`MOVSB、MOVSW、MOVSD`這三條指令,該指令的原理為從`ESI`到`EDI`中,執(zhí)行后將ESI地址里面的內(nèi)容移動到EDI指向的內(nèi)存空間中,該指令常用于對特定字符串的復制操作。


?- MOVSB指令:將一個字節(jié)從ESI地址指向的內(nèi)存單元復制到EDI地址指向的內(nèi)存單元,同時增加或減少ESI和EDI(取決于方向標志位的狀態(tài))。

?- MOVSW指令:將兩個字節(jié)從ESI地址指向的內(nèi)存單元復制到EDI地址指向的內(nèi)存單元,

?- MOVSD指令:將四個字節(jié)從ESI地址指向的內(nèi)存單元復制到EDI地址指向的內(nèi)存單元。這些指令都可用于復制字符串或移動緩沖區(qū)。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? ; 逐字節(jié)拷貝

? SrcString? ? BYTE "hello lyshark",0h? ? ? ; 源字符串

? SrcStringLen EQU $ - SrcString - 1? ? ? ? ; 計算出原始字符串長度

? DstString? ? BYTE SrcStringLen dup(?),0h? ; 目標內(nèi)存地址

? szFmt BYTE '字符串: %s 長度: %d ',0dh,0ah,0

??

? ; 四字節(jié)拷貝

? ddSource DWORD 10h,20h,30h? ? ? ? ? ? ? ?; 定義三個四字節(jié)數(shù)據(jù)

? ddDest? ?DWORD lengthof ddSource dup(?)? ; 得到目標地址


.code

? main PROC

? ? ; 第一種情況: 實現(xiàn)逐字節(jié)拷貝

? ? cld? ? ? ? ? ? ? ? ? ? ? ? ?; 清除方向標志

? ? mov esi,offset SrcString? ? ; 取源字符串內(nèi)存地址

? ? mov edi,offset DstString? ? ; 取目標字符串內(nèi)存地址

? ? mov ecx,SrcStringLen? ? ? ? ; 指定循環(huán)次數(shù),為原字符串長度

? ? rep movsb? ? ? ? ? ? ? ? ? ?; 逐字節(jié)復制,直到ecx=0為止

? ??

? ? lea eax,dword ptr ds:[DstString]

? ? mov ebx,sizeof DstString

? ? invoke crt_printf,addr szFmt,eax,ebx

? ??

? ? ; 第二種情況: 實現(xiàn)4字節(jié)拷貝

? ? lea esi,dword ptr ds:[ddSource]

? ? lea edi,dword ptr ds:[ddDest]

? ? cld

? ? rep movsd

? ??

? ? ; 使用loop循環(huán)逐字節(jié)復制

? ? lea esi,dword ptr ds:[SrcString]

? ? lea edi,dword ptr ds:[DstString]

? ? mov ecx,SrcStringLen

? ? cld? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; 設置方向為正向復制

? @@: movsb? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; 每次復制一個字節(jié)

? ? dec ecx? ? ? ? ? ? ? ? ? ? ? ? ? ?; 循環(huán)遞減

? ? jnz @B? ? ? ? ? ? ? ? ? ? ? ? ? ? ; 如果ecx不為0則循環(huán)

? ??

? ? lea eax,dword ptr ds:[DstString]

? ? mov ebx,sizeof DstString

? ? invoke crt_printf,addr szFmt,eax,ebx

? ??

? ? invoke ExitProcess,0

? main ENDP

END main

```


### 3.2 CMPSB/CMPSW/CMPSD


比較串指令包括`CMPSB、CMPSW、CMPSD`比較`ESI、EDI`執(zhí)行后將ESI指向的內(nèi)存操作數(shù)同EDI指向的內(nèi)存操作數(shù)相比較,其主要從ESI指向內(nèi)容減去EDI的內(nèi)容來影響標志位。這些指令通常用于比較字符串中的字符,可影響方向標志、零標志和符號標志位的狀態(tài)。


CMPSB指令是將ESI和EDI地址指向的內(nèi)存單元中的一個字節(jié)進行比較,同時增加或減少ESI和EDI(取決于方向標志位的狀態(tài))。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? ; 逐字節(jié)比較

? SrcString? ? BYTE "hello lyshark",0h

? DstStringA? ?BYTE "hello world",0h

.const

? szFmt BYTE '字符串: %s',0dh,0ah,0

? YES BYTE "相等",0

? NO? BYTE "不相等",0

??

.code

? main PROC

? ? ; 實現(xiàn)字符串對比,相等/不相等輸出

? ? lea esi,dword ptr ds:[SrcString]

? ? lea edi,dword ptr ds:[DstStringA]

? ? mov ecx,lengthof SrcString

? ? cld

? ? repe cmpsb

? ? je L1

? ? jmp L2


? L1: lea eax,YES

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end


? L2: lea eax,NO

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end

? lop_end:

? ? int 3


? ? invoke ExitProcess,0

? main ENDP

END main

```


CMPSW 是對比一個字類型的數(shù)組,指令是將ESI和EDI地址指向的內(nèi)存單元中的兩個字節(jié)進行比較,只有當數(shù)組中的數(shù)據(jù)完全一致的情況下才會返回真,否則為假。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? Array1 WORD 1,2,3,4,5? ? ? ; 必須全部相等才會清空ebx

? Array2 WORD 1,3,5,7,9

.const

? szFmt BYTE '數(shù)組: %s',0dh,0ah,0

? YES BYTE "相等",0

? NO? BYTE "不相等",0

??

.code

? main PROC

? ? lea esi,Array1

? ? lea edi,Array2

? ? mov ecx,lengthof Array1

? ??

? ? cld

? ? repe cmpsw

? ? je L1

? ? lea eax,NO

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end


? L1: lea eax,YES

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end

??

? lop_end:

? ? int 3


? ? invoke ExitProcess,0

? main ENDP

END main

```


CMPSD則是比較雙字數(shù)據(jù),指令將ESI和EDI地址指向的內(nèi)存單元中的四個字節(jié)進行比較,同樣可用于比較數(shù)組,這里就演示一下比較單數(shù)的情況。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? var1 DWORD 1234h

? var2 DWORD 5678h

.const

? szFmt BYTE '兩者: %s',0dh,0ah,0

? YES BYTE "相等",0

? NO? BYTE "不相等",0

??

.code

? main PROC

? ? lea esi,dword ptr ds:[var1]

? ? lea edi,dword ptr ds:[var2]

? ??

? ? cmpsd

? ? je L1

? ? lea eax,dword ptr ds:[YES]

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end

? ??

? L1: lea eax,dword ptr ds:[NO]

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end


? lop_end:

? ? int 3


? ? invoke ExitProcess,0

? main ENDP

END main

```


### 3.3 SCASB/SCASW/SCASD


掃描串指令包括`SCASB、SCASW、SCASD`其作用是把`AL/AX/EAX`中的值同EDI尋址的目標內(nèi)存中的數(shù)據(jù)相比較,這些指令在一個長字符串或者數(shù)組中查找一個值的時候特別有用。


?- SCASB指令:將AL寄存器中的值與EDI地址指向的內(nèi)存單元中的一個字節(jié)進行比較,同時增加或減少EDI(取決于方向標志位的狀態(tài))。

?- SCASW指令:將AX寄存器中的值與EDI地址指向的內(nèi)存單元中的兩個字節(jié)進行比較。

?- SCASD指令:將EAX寄存器中的值與EDI地址指向的內(nèi)存單元中的四個字節(jié)進行比較。這些指令通常用于在一個長字符串或數(shù)組中查找一個特定值的位置,可影響方向標志、零標志和符號標志位的狀態(tài)。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? szText BYTE "ABCDEFGHIJK",0

.const

? szFmt BYTE '字符F所在位置: %d',0dh,0ah,0


.code

? main PROC

? ? ; 尋找單一字符找到會返回第幾個字符

? ? lea edi,dword ptr ds:[szText]

? ? mov al,"F"

? ? mov ecx,lengthof szText -1

? ? cld

? ? repne scasb? ? ? ? ? ? ? ? ?; 如果不相等則重復掃描

? ? je L1

? ? xor eax,eax? ? ? ? ? ? ? ? ?; 如果沒找到F則清空eax

? ? jmp lop_end

? ??

? L1: sub ecx,lengthof szText -1

? ? neg ecx? ? ? ? ? ? ? ? ? ? ?; 如果找到輸出第幾個字符

? ? invoke crt_printf,addr szFmt,ecx

??

? lop_end:

? ? int 3


? main ENDP

END main

```


如果我們想要對數(shù)組中某個值是否存在做判斷,則可以使用SCASD指令掃描一個數(shù)組中是否存在一個特定的值,通過循環(huán)指令(如LOOP或JECXZ)逐個4字節(jié)掃描,來檢查EAX寄存器中的值是否與目標數(shù)組中的值匹配。如果匹配成功,則方向標志位將被設置為與掃描方向相反的方向,如果沒有找到匹配項,方向標志位將保持不變。


在使用循環(huán)指令時,需要在每次循環(huán)中比較數(shù)組當前位置的值是否與目標值相等,如果相等就跳出循環(huán),如果沒有找到匹配項,就繼續(xù)循環(huán)指令知道數(shù)組的最后元素。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? MyArray DWORD 65,88,93,45,67,89,34,67,89,22

.const

? szFmt BYTE '數(shù)值: %d 存在',0dh,0ah,0

.code

? main PROC

? ? lea edi,dword ptr ds:[MyArray]

? ? mov eax,34

? ? mov ecx,lengthof MyArray - 1

? ? cld

? ? repne scasd

? ? je L1

? ? xor eax,eax

? ? jmp lop_end


? L1: sub ecx,lengthof MyArray - 1

? ? neg ecx

? ? invoke crt_printf,addr szFmt,ecx,eax

? lop_end:

? ? int 3


? main ENDP

END main

```


### 3.4 STOSB/STOSW/STOSD


存儲指令主要包括`STOSB、STOSW、STOSD`其作用是把`AL/AX/EAX`中的數(shù)據(jù)儲存到EDI給出的地址中,執(zhí)行后EDI的值根據(jù)方向標志的增加或減少,該指令常用于初始化內(nèi)存或堆棧。


?- STOSB指令:將AL寄存器中的值存儲到EDI地址指向的內(nèi)存單元中,同時增加或減少EDI(取決于方向標志位的狀態(tài))。

?- STOSW指令:將AX寄存器中的值存儲到EDI地址指向的兩個字節(jié)內(nèi)存單元中。

?- STOSD指令:將EAX寄存器中的值存儲到EDI地址指向的四個字節(jié)內(nèi)存單元中。這些指令常用于初始化內(nèi)存、堆棧和緩沖區(qū)。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? Count? DWORD 100

? String BYTE 100 DUP(?),0


.code

? main PROC

??

? ? ; 利用該指令初始化字符串

? ? mov al,0ffh? ? ? ? ? ? ? ? ? ?; 初始化填充數(shù)據(jù)

? ? lea di,byte ptr ds:[String]? ?; 待初始化地址

? ? mov ecx,Count? ? ? ? ? ? ? ? ?; 初始化字節(jié)數(shù)

? ? cld? ? ? ? ? ? ? ? ? ? ? ? ? ?; 初始化:方向=前方

? ? rep stosb? ? ? ? ? ? ? ? ? ? ?; 循環(huán)填充

? ??

? ? ; 存儲字符串: 使用A填充內(nèi)存

? ? lea edi,dword ptr ds:[String]

? ? mov al,"A"

? ? mov ecx,Count

? ? cld

? ? rep stosb


? ? int 3


? main ENDP

END main

```


### 3.5 LODSB/LODSW/LODSD


載入指令主要包括`LODSB、LODSW、LODSD`起作用是將ESI指向的內(nèi)存位置向`AL/AX/EAX`中裝載一個值,同時ESI的值根據(jù)方向標志值增加或減少,如下分別完成加法與乘法計算,并回寫到內(nèi)存中。


?- LODSB指令:將ESI地址指向的一個字節(jié)復制到AL寄存器中,同時增加或減少ESI(取決于方向標志位的狀態(tài))。

?- LODSW指令:將ESI地址指向的兩個字節(jié)復制到AX寄存器中

?- LODSD指令:將ESI地址指向的四個字節(jié)復制到EAX寄存器中。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? ArrayW? ? ? WORD 1,2,3,4,5,6,7,8,9,10

? ArrayDW? ? ?DWORD 1,2,3,4,5

? ArrayMulti? DWORD 10

??

? szFmt BYTE '計算結(jié)果: %d ',0dh,0ah,0


.code

? main PROC

? ? ; 利用載入命令計算數(shù)組加法

? ? lea esi,dword ptr ds:[ArrayW]

? ? mov ecx,lengthof ArrayW

? ? xor edx,edx

? ? xor eax,eax

? @@: lodsw? ? ? ? ? ; 將輸入加載到EAX

? ? add edx,eax

? ? loop @B

? ??

? ? mov eax,edx? ? ; 最后將相加結(jié)果放入eax

? ? invoke crt_printf,addr szFmt,eax

? ??

? ? ; 利用載入命令(LODSD)與存儲命令(STOSD)完成乘法運算

? ? mov esi,offset ArrayDW? ?; 源指針

? ? mov edi,esi? ? ? ? ? ? ? ; 目的指針

? ? cld? ? ? ? ? ? ? ? ? ? ? ; 方向=向前

? ??

? ? mov ecx,lengthof ArrayDW ; 循環(huán)計數(shù)器

? L1: lodsd? ? ? ? ? ? ? ? ? ? ; 加載[esi]至EAX

? ? mul ArrayMulti? ? ? ? ? ?; 將EAX乘以10

? ? stosd? ? ? ? ? ? ? ? ? ? ; 將結(jié)果從EAX存儲至[EDI]

? ? loop L1

? ??

? ? ; 循環(huán)讀取數(shù)據(jù)(存在問題)

? ? mov esi,offset ArrayDW? ? ?; 獲取基地址

? ? mov ecx,lengthof ArrayDW? ?; 獲取長度

? ? xor eax,eax

? @@: lodsd

? ? invoke crt_printf,addr szFmt,eax

? ? dec ecx

? ? loop @B?


? ? int 3


? main ENDP

END main

```


本文作者: 王瑞

本文鏈接: https://www.lyshark.com/post/f6603608.html

版權聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請注明出處!


5.3 匯編語言:字符串操作指令的評論 (共 條)

分享到微博請遵守國家法律
南城县| 白山市| 邯郸市| 喀喇沁旗| 宿州市| 固原市| 盐池县| 巍山| 海原县| 西藏| 南丰县| 抚顺市| 汶上县| 阿荣旗| 烟台市| 武清区| 北辰区| 南安市| 罗定市| 繁昌县| 双流县| 德保县| 西吉县| 鄂托克旗| 景谷| 土默特左旗| 江西省| 莒南县| 新河县| 巴楚县| 秭归县| 精河县| 绍兴市| 霸州市| 布尔津县| 临沂市| 丹凤县| 临清市| 长葛市| 福清市| 阿勒泰市|