Win32汇编:字符串操作指令
移动串指令: MOVSB、MOVSW、MOVSD ;从 ESI -> EDI; 执行后, ESI 与 EDI 的地址移动相应的单位
比较串指令: CMPSB、CMPSW、CMPSD ;比较 ESI、EDI; 执行后, ESI 与 EDI 的地址移动相应的单位
扫描串指令: SCASB、SCASW、SCASD ;依据 AL/AX/EAX 中的数据扫描 EDI 指向的数据, 执行后 EDI 自动变化
储存串指令: STOSB、STOSW、STOSD ;将 AL/AX/EAX 中的数据储存到 EDI 给出的地址, 执行后 EDI 自动变化
载入串指令: LODSB、LODSW、LODSD ;将 ESI 指向的数据载入到 AL/AX/EAX, 执行后 ESI 自动变化
其中的 B、W、D 分别指 Byte、Word、DWord, 表示每次操作的数据的大小单位.
上述指令可以有重复前缀:
REP ECX > 0 时
REPE (或 REPZ) ECX > 0 且 ZF=1 时
REPNE(或 REPNZ) ECX > 0 且 ZF=0 时
;重复前缀可以自动按单位(1、2、4)递减 ECX
字符串复制(movsb):
.data
string1 db "hello lyshark",0 ; 原始字符串
str_len equ $ - string1 -1 ; 计算出原始字符串长度
string2 db str_len dup(?),0 ; 目标内存地址
.code
main PROC
cld ; 清除方向标志
mov esi,offset string1 ; 取源字符串内存地址
mov edi,offset string2 ; 取目标字符串内存地址
mov ecx,str_len ; 指定循环次数,为原字符串长度
rep movsb ; 逐字节复制,直到ecx=0为止
ret
main ENDP
END main
另一种字串复制(movsb): 不使用rep重复前缀的方式完成字串复制.
.data
string1 db "hello lyshark",0 ; 原始字符串
str_len equ $ - string1 -1 ; 计算出原始字符串长度
string2 db str_len dup(?),0 ; 目标内存地址
.code
main PROC
lea esi,string1 ; 取string1的地址
lea edi,string2 ; 取string2的地址
mov ecx,str_len ; 取字符串长度,用于循环
cld ; 方向->正向
@@: movsb ; 每次复制一个字节BYTE
dec ecx ; 每次ecx减一
jnz @B ; 如果ecx不为0则循环
ret
main ENDP
END main
(movsd)四字节复制字串:
.data
ddSource DWORD 10h,20h,30h ; 定义三个四字节数据
ddDest DWORD lengthof ddSource dup(?) ; 得到目标地址
.code
main PROC
lea esi,ddSource
lea edi,ddDest
mov ecx,lengthof ddSource
cld
rep movsd
ret
main ENDP
END main
CMPSB:
.data
Text1 db "hello lyshark",0
Text2 db "hello lyshar1",0
.code
main PROC
lea esi,Text1
lea edi,Text2
mov ecx,lengthof Text1
cld
repe cmpsb
je L1
xor eax,eax ; 字串不同则清空eax
jmp L2
L1: xor ebx,ebx ; 字串相同则清空ebx
L2: ret
main ENDP
END main
CMPSD: 比对两个双字数据是否相等.
.data
var1 DWORD 1234h
var2 DWORD 5678h
.code
main PROC
lea esi,var1
lea edi,var2
cmpsd
je L1
xor eax,eax ; 两数如果相等则清空eax
jmp L2
L1: xor ebx,ebx ; 两数不相等则清空ebx
L2: ret
main ENDP
END main
CMPSW:
.data
Array1 WORD 1,2,3,4,5 ; 必须全部相等才会清空ebx
Array2 WORD 1,3,5,7,9
.code
main PROC
lea esi,Array1
lea edi,Array2
mov ecx,lengthof Array1
cld
repe cmpsw
je L1
xor eax,eax ; 两数不相等则清空eax
jmp L2
L1: xor ebx,ebx ; 两数相等则清空ebx
L2: ret
main ENDP
END main
SCASB 扫描字串: 依据 AL/AX/EAX 中的数据扫描 EDI 指向的数据, 执行后 EDI 自动变化
.data
szText BYTE "ABCDEFGHIJK",0
.code
main PROC
lea edi,szText
mov al,"F"
mov ecx,lengthof szText -1
cld
repne scasb ; 如果不相等则重复
je L1
xor eax,eax ; 如果没找到F则清空eax
jmp L2
L1: sub ecx,lengthof szText -1
neg ecx ; 如果找得到, 这里显示是第几个字符; 本例结果是 6
L2: ret
main ENDP
END main
STOSB 存储字串: 将 AL/AX/EAX 中的数据储存到 EDI 给出的地址, 执行后 EDI 自动变化
.data
len = 10
szText db len dup(0),0
.code
main PROC
lea edi,szText ; EDI指向字符串
mov al,"W" ; 定义查找字母为W
mov ecx,len ; 设置查找计数器
cld ; 方向=正向
rep stosb ; ecx>0则执行
ret
main ENDP
END main
LODSW 载入指令: 将 ESI 指向的数据载入到 AL/AX/EAX, 执行后 ESI 自动变化,如下是累加求和
.data
Array WORD 1,2,3,4,5,6,7,8,9,10
.code
main PROC
lea esi,Array
mov ecx,lengthof Array
xor edx,edx
xor eax,eax
@@: lodsw
add edx,eax
loop @B
mov eax,edx ; 最后将相加结果放入eax
main ENDP
END main
初始化内存: 把String字符串中的,每一个字节均填充初始化为0FFh
.data
Count = 100 ; 申请空间为100
String BYTE Count DUP(?) ; 初始化为BYTE
.code
main PROC
mov al,0FFh ; 指定要填充的数据为0FFh
mov edi,offset String ; EDI寄存器指向目标内存
mov ecx,Count ; 循环计数
cld ; 初始化:方向=前方
rep stosb ; 以AL中的值进行填充
ret
main ENDP
END main
数组的乘法: 把双字数组中的每一个元素分别乘以一个常量,程序中使用了(LODSD加载),(STOSD保存)
.
.data
Array DWORD 1,2,3,4,5
Multi DWORD 10
.code
main PROC
mov esi,offset Array ; 源指针
mov edi,esi ; 目的指针
cld ; 方向=向前
mov ecx,lengthof Array ; 循环计数器
L1: lodsd ; 加载[esi]至EAX
mul Multi ; 将EAX乘以10
stosd ; 将结果从EAX存储至[EDI]
loop L1
ret
main ENDP
END main
计算字符串长度: 以下代码用于计算字符串的长度,并将结果保存在EAX寄存器中.
.data
String BYTE "hello world",0 ; 带计算字符串
.code
main PROC
mov edi,offset String ; 取出字符串的基地址
xor eax,eax ; 清空eax用作计数器
L1: cmp byte ptr [edi],0 ; 分别那[edi]的值和0作比较
je L2 ; 上一步为零则跳转得到ret
inc edi ; 否则继续执行
inc eax
jmp L1
L2: ret
main ENDP
END main
小写字串转大写: 将MyString变量中的小写字符串,依次转换为大写字符串.
.data
MyString db "hello lyshark",0 ; 定义MyString字符串
.code
main PROC
mov esi,offset MyString ; 取出字符串的偏移地址
L1: cmp byte ptr [esi],0 ; 分别拿出每一个字节,与0比较
je L2 ; 如果相等则跳转到L2
and byte ptr [esi],11011111b ; 执行按位与操作
inc esi ; 每次esi指针递增1
jmp L1 ; 重复循环
L2: ret
main ENDP
END main
定义二维数组: 定义一个二维数组Table,并取出第一行中的第2偏移地址的元素.
.data
Table WORD 10h,20h,30h,40h,50h ; 定义一个数组
Row = ($ - Table) ; 取出数组每行的字节数
WORD 60h,70h,80h,90h,0Ah ; 继续定义数组
.code
main PROC
row_index = 1 ; 表的偏移地址
column_index = 2 ; 行的偏移地址
mov ebx,offset Table ; 取偏移地址给ebx
add ebx,Row*row_index ; 每行元素*偏移
mov esi,column_index ; 将行偏移赋值给esi
mov ax,[ebx+esi*TYPE Table] ; Table比例因子只能是2,4,8
main ENDP
END main
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!