当前位置:科技动态 > strcmp函数 VS2010_回调函数的范例———VS2010 下编译

strcmp函数 VS2010_回调函数的范例———VS2010 下编译

  • 发布:2023-09-15 20:39

MASM32+Visual 2010 编辑字符函数

一.实验目的

利用MASM32+Visual 2010,利用汇编语言,写出如下字符函数:

(1)strset (2)strlen (3)strcmp

(4)strchr (5)memset (6)memcpy

二.环境配置

参考:MASM32+Visual studio 2010写汇编程序入门

连接:https://www.sychzs.cn/MaxWoods/article/details/44649685?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160182254019725222408586%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&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%2bVisual%20studio%202010%E5%86%99%E6%B1%87%E7%BC%96%E7%A8%8B%E5%BA%8F&spm=1018.2118.3001.4187

三.MASM32入门

假如学过微机原理,但是对 VS2010汇编编程不太熟悉的话,请参阅下文:

[入门masm32编写简单汇编程序并做具体分析](https://www.sychzs.cn/codes_first/article/details/78279641?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160179651419724848341514%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&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%E5%86%99%E6%B1%87%E7%BC%96%E7%A8%8B%E5%BA%8F%E5%85%A5%E9%97%A8&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 www.sychzs.cn

includelib kernel32.lib

include www.sychzs.cn

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 www.sychzs.cn

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 www.sychzs.cn

includelib kernel32.lib

include www.sychzs.cn

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

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 www.sychzs.cn

includelib kernel32.lib

include www.sychzs.cn

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 www.sychzs.cn

includelib kernel32.lib

include www.sychzs.cn

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 www.sychzs.cn

includelib kernel32.lib

include www.sychzs.cn

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)结果展示

多字节函数在Unicode下对应的函数:

strcmp => wcscmp

strlen => lstrlen

strcpy => wcscpy

sscanf => swscanf

sprintf => wsprintf

char => wchar_t

atof => _wtof

atoi => _wtoi

LPCSTR => LPCTSTR LPCTSTR => LPCWSTR

?

注:更改界面文件为Unicode两个步骤: 1、先将xxx.rc文件以查看代码方式打开, 然后另存为,在【保存】按钮右边三角选择【以编码方式保存】, 选择【Unicode - 代码页1200】保存, 2、右键各个界面资源,选择【插入副本】,选择对应语言, 插入后,修改各个界面各个按钮文本即可

?

?

?

?

?

1.回调函数范例一,在VS2010下编译通过

#include "stdafx.h"

#include

void printWelcome(int len)

{

printf("欢迎欢迎 -- %d\n", len);

}

void printGoodbye(int len)

{

printf("送客送客 -- %d\n", len);

}

void callback(int times, void (* print)(int))

{

int i;

for (i = 0; i < times; ++i)

{

print(i);

}

printf("\n我不知道你是迎客还是送客!\n\n");

}

void main(void)

{

callback(10, printWelcome);

callback(10, printGoodbye);

printWelcome(5);

}

运行结果如下

2.回调函数的范例二,在VS2010 下编译,通过

#include

#include

#include

#include "stdafx.h"

int my_strcmp(char* des, char* src);

static void cmd_hello(void);

static void cmd_hi(void);

static void cmd_exit(void);

//定义一个函数指针

typedef void (*callback)(void);

//定义命令结构体

typedef struct cmd{

char name[10]; //命令的名字

callback func; //与命令相对应的函数指针

}cmd_t;

//然后定义一个命令数组:

//声明命令数组

cmd_t cmd_tbl[] = {

{"hello",cmd_hello},

{"hi",cmd_hi},

{"exit",cmd_exit},

};

//  跟命令相对应的函数为:

//相对应的功能函数为:

void hello(void)

{

printf("hello\n");

}

void hi(void)

{

printf("hi\n");

}

static void cmd_hello(void)

{

hello();

}

static void cmd_hi(void)

{

hi();

}

static void cmd_exit(void)

{

//exit(0);

}

//此时我们还需要一个查找命令函数:

cmd_t* my_find( char* val)

{

int i;

for(i = 0; i < sizeof(cmd_tbl)/sizeof(cmd_tbl[0]); i++){

if(!my_strcmp(val,cmd_tbl[i].name)){

return &cmd_tbl[i];

}

}

return 0;

}

//字符串比较函数

int my_strcmp(char* des, char* src)

{

while(*des){

if(*des != *src)

return 1;

des++;

src++;

}

return *src - *des;

}

//此函数返回的是一个结构体指针,若没有找到命令则返回0;

//main 函数如下:

int main(void){

char val[20] = {};

cmd_t *cmd_ptr;

while(1){

gets(val);

cmd_ptr = my_find(val);

if(cmd_ptr){

cmd_ptr->func();

}

else{

printf("no cmd\n");

}

}

return 0;

}

运行结果:

相关文章

最新资讯