MASM32+Visual 2010 编辑字符函数
一.实验目的
利用MASM32+Visual 2010,利用汇编语言,写出如下字符函数:
(1)strset (2)strlen (3)strcmp
(4)strchr (5)memset (6)memcpy
二.环境配置
参考:MASM32+Visual studio 2010写汇编程序入门
连接:https://blog.csdn.net/MaxWoods/article/details/44649685?ops_request_misc=%7B%22request%5Fid%22%3A%22160182254019725222408586%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=160182254019725222408586&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-44649685.pc_first_rank_v2_rank_v28&utm_term=MASM32+Visual studio 2010写汇编程序&spm=1018.2118.3001.4187
三.MASM32入门
假如学过微机原理,但是对 VS2010汇编编程不太熟悉的话,请参阅下文:
[入门masm32编写简单汇编程序并做具体分析](https://blog.csdn.net/codes_first/article/details/78279641?ops_request_misc=%7B%22request%5Fid%22%3A%22160179651419724848341514%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fall.%22%7D&request_id=160179651419724848341514&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-78279641.pc_first_rank_v2_rank_v28&utm_term=MASM32写汇编程序入门&spm=1018.2118.3001.4187)
四.思路与代码详解
3.1.strset函数
(1)strset函数功能
strset(string s,char c)——>将字符串s中所有的字符设置成c
(2)程序流图
step1:设置指针指向需要改变的字符串
step2:比较:此指针所指的字节值<——>0
step3:如果不相等,将此指针所指的字节值变为字符c,更新指针
step4:否则,更新指针,转到step2
(3)代码实现
.386
.model flat
, stdcall
include kernel32
.inc
includelib kernel32
.lib
include msvcrt
.inc
includelib msvcrt
.lib
.data
szText db
"Reverse Engineering", 0
chr db
'j'
.code
main PROC
LEA EDI
, szText
MOV ECX
,0FFFFFFFFH
XOR EAX
,EAX
;将EAX置为
0
MOV AL
,chr
;将低位AL置为j
change
:
MOV
[EDI
],AL
;将j放入sztext中,将其中的一个字符变为J
ADD EDI
,1 ;改变地址,使得地址增加
CMP BYTE PTR
[EDI
],0 ;观察一下,看这个字符是不是为
0
JNZ change
;如果不是的话,就继续change循环
INVOKE crt_printf
, addr szText
;将sztext打印出来
INVOKE crt_getchar
INVOKE ExitProcess
, 0
main ENDP
END main
注意:上述代码中:
.386
.model flat,stdcall
include kernel32.inc
includelib kernel32.lib
...
这些代码段,均是使用C++进行汇编的一般架构,在上述连接:入门masm32编
写简单汇编程序并做具体分析中,有详细的叙述。
(4)结果展示
将"Reverse Engineering"全部转为"jjjj...jjjjj"
3.2.strlen函数
(1)strlen函数功能
int strset(string s)——>计算字符串s的长度
(2)程序流图
step1:设置指针指向需要计算长度的字符串,设置记录长度的寄存器初始为0
step2:比较:此指针所指的字节值<——>0
step3:如果不为0,将记录长度的寄存器+1,更新指针
step4:否则,说明字符串已经到结尾,结束程序
(3)代码实现
.386
.model flat
, stdcall
include kernel32
.inc
includelib kernel32
.lib
include msvcrt
.inc
includelib msvcrt
.lib
.data
szText db
"xie chuan long is shuai", 0
format db
"length = %d", 0AH
, 0
.code
main PROC
LEA EDI
, szText
;将字符串的初始地址放到EDI中去
MOV ECX
,0FFFFFFFFH
MOV EAX
,0 ;计数,初始值设为
0
count
:
CMP BYTE PTR
[EDI
],0 ;比较
[EDI
]的值(字符串的某个字符)是否为\
0
PUSHFD
;将标志寄存器压入栈中
ADD EDI
,1 ;将地址位
+1
INC EAX
;还没看出
[EDI
]是否为\
0,先加上再说
POPFD
;将标志寄存器出栈
LOOPNZ count
;观察ZF是否为
0,如果不为
0,循环count
DEC EAX
;因为最后把\
0也加上了,所以要减去
1
INVOKE crt_printf
, addr format
, EAX
INVOKE crt_getchar
INVOKE ExitProcess
, 0
main ENDP
END main
(4)结果展示
计算"xie chuan long is shuai"的长度=23
3.3.strcmp函数
(1)strcmp函数功能
int strcmp(string s1,string s2):如果s1=s2,输出为0;如果s1>s2
(s2更短,或s2对应字符的ASCII更小),输出为1;如果前两种情况都不是
,输出为-1。
(2)程序流图
注意:s1(i)的含义为:s1字符串的第i个字符
(3)代码实现
szText db
"Reverse Engineering", 0
szText2 db
"Reverse Engineering", 0 ;szText
==szText2
szText3 db
"Reverse Eng", 0 ;szText
>szText3
szText4 db
"Reverse Engj", 0 ;szText
<szText4
szText5 db
"Reverse Engh", 0 ;szText
>szText5
.code
main PROC
LEA ESI
, szText
LEA EDI
, szText2
;result
=0
;LEA EDI
, szText3
;result
=1
;LEA EDI
, szText4
;result
=-1
;LEA EDI
, szText5
;result
=1
;话不多说,都在图中
compare
:
MOV BL
,[EDI
]
CMP BYTE PTR
[ESI
],BL
JNE noequal
CMP BYTE PTR
[ESI
],0
JE equal
ADD ESI
,1
ADD EDI
,1
JMP compare
equal
:
MOV EAX
,0
JMP print
noequal
:
MOV BL
,[EDI
]
CMP BYTE PTR
[ESI
],BL
JA bigger
smaller
:
MOV EAX
,-1
JMP print
bigger
:
MOV EAX
,1
print
:
INVOKE crt_printf
, addr format
, EAX
;EAX
=result
INVOKE crt_getchar
INVOKE ExitProcess
, 0
main ENDP
END main
(4)结果展示
情况一:s1=szText s2=szText2="Reverse Engineering"
情况二:s1=szText s2=szText3="Reverse Eng"
或者 s1=szText s2=szText5="Reverse Engh"。输出相同结果。
情况三:s1=szText s2=szText4="Reverse Engj"
3.4.strchr函数
(1)strchr函数功能
int strchr(string s,char d)——>找到字符d在字符串s中的位置
(2)程序流图
(3)代码实现
.386
.model flat
, stdcall
include kernel32
.inc
includelib kernel32
.lib
include msvcrt
.inc
includelib msvcrt
.lib
.data
szText db
"Reverse Engineering", 0
chr db
'i'
format db
"%d", 0AH
, 0
result db
"The program is over",0
.code
main PROC
LEA EDI
, szText
MOV ECX
,0FFFFFFFFH
MOV EBX
,1 ;EBX记录现在在字符串的哪个位置
equ0
:
MOV CL
,chr
;将要寻找的字符给CL
CMP BYTE PTR
[EDI
],0 ;比较现在EDI所在的位置字符是否为
0
JE over
;如果为
0,则程序结束
CMP BYTE PTR
[EDI
],CL
;否则,比较EDI所在字符是否为要找的字符
'i'
JNE noprint
;如果不是,则直接开启下一个equ0循环
INVOKE crt_printf
, addr format
,EBX
;我们找到了
'i'并输出,但是也许后面也有
'i'哦
!
noprint
:
ADD EDI
,1
ADD EBX
,1
JMP equ0
over
:
INVOKE crt_printf
, addr result
INVOKE crt_getchar
INVOKE ExitProcess
, 0
main ENDP
END main
(4)结果展示
输出字符串"xie chuan long,i love you"中'i'字符的位置:
3.5.memset函数
(1)memset函数功能
void *memset(string s,char d,int size)——>将字符串s前size个字节用字符d替换
(2)程序流图
这个程序逻辑很简单,与前面strlen类型相似,在此不做描述。代码中有注释。
(3)代码实现
.386
.model flat
, stdcall
include kernel32
.inc
includelib kernel32
.lib
include msvcrt
.inc
includelib msvcrt
.lib
.data
szText db
"xie chuan long is shuaige", 0
chr db
'x'
siz db
3
format db
"%d", 0AH
, 0
.code
main PROC
LEA EDI
,szText
MOV ECX
,0FFFFFFFFH
XOR ECX
,ECX
XOR EDX
,EDX
MOV DH
,chr
;将要重复的字符chr
->DH
MOV CL
,siz
;将要复制的长度siz
->CL
change
:
CMP CL
,0 ;比较CL是否为
0,如果为
0,则输出转换后的结果
JE print
MOV
[EDI
],DH
;将siz
->EDI所处位置
ADD EDI
,1 ;更新EDI与CL
DEC CL
JMP change
print
:
INVOKE crt_printf
, addr szText
INVOKE crt_getchar
INVOKE ExitProcess
, 0
main ENDP
END main
(4)结果展示
将字符串"xie chuan long is shuaige"前三个字符变为"x":
3.6.memcpy函数
(1)memcpy函数功能
void *memcpy(void *destin, void *source, unsigned n)——>将source所指字节按顺序给destin,字节长度为n
(2)程序流图
这个程序逻辑也很简单,在此不做描述。代码中有注释。
(3)代码实现
.386
.model flat
, stdcall
include kernel32
.inc
includelib kernel32
.lib
include msvcrt
.inc
includelib msvcrt
.lib
.data
szText db
"xie chuan long is shuaige", 0
chr db
128 dup(0)
format db
"%d", 0AH
, 0
.code
main PROC
LEA EDI
,szText
;EDI指向要复制的字符串,ESI指向目的地址
LEA ESI
,chr
MOV ECX
,0FFFFFFFFH
copy
:
CMP BYTE PTR
[EDI
],0 ;判断此时
[EDI
]是否为
0
JE print
;如果为
0,说明字符串已经到末尾,应该结束了
PUSH
[EDI
] ;将
[EDI
]->[ESI
]
POP
[ESI
]
ADD EDI
,1 ;将EDI与ESI增加
1
ADD ESI
,1
JMP copy
print
:
INVOKE crt_printf
, addr chr
INVOKE crt_getchar
INVOKE ExitProcess
, 0
main ENDP
END main
(4)结果展示