抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

用win32汇编语言实现以下C语言函数,

  1. strlen()

  2. strcmp()

  3. strchr()

安装MASM

在官网下载https://www.masm32.com/

解压文件夹到指定盘符。

配置MASM路径

控制面板->系统和安全-> 系统 -> 高级系统设置 -> 环境变量 -> 系统变量

将masm相关路径添加到系统变量

1
2
变量名:include
变量值:%Masm32Dir%\Include;
1
2
变量名:lib
变量值:%Masm32Dir%\lib;
1
2
变量名:Masm32Dir
变量值: C:\masm32 //填入自己的masm安装路径
1
2
变量名:path
变量值:%Masm32Dir%\Bin;%Masm32Dir%;C:\Users\admin\AppData\Local\Microsoft\WindowsApps;C:\masm32\bin;

代码

strlen()

strlen.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
.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

.code

main PROC
LEA EDI, szText
MOV ECX,0FFFFFFFFH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;strlen逻辑
MOV EAX,0 ;计数
count: ;此过程体用于计量字符数目
CMP BYTE PTR [EDI],0 ;将每一个字符与字符串结束符'\0'比较
PUSHFD ;将状态标志位入栈
ADD EDI,1 ;增加字符串索引
INC EAX ;不管三七二十一,先给计数值+1
POPFD ;将状态标志位出栈
LOOPNZ count ;若此字符不等于'\0',则跳转回count继续计数
DEC EAX ;由于最后将字符='\0'的情况也计数了,所以需要给计数值-1
INVOKE crt_printf,addr format,EAX ;这里调用过程把计数值打印出来,perfecct!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP

END main


strchr()

strchr.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.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

.code

main PROC
LEA EDI, szText
MOV ECX,0FFFFFFFFH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;strchr逻辑
;1.题目要求返回位置指针,但是打印指针对于判断准确性并不直观。我选用数组下标代替
;2.由于要求在未找到时返回零,故而这里数组下标的初始值是一
MOV AH,1 ;AH用于存储数组下标,从一开始
stringLocate: ;字符串定位过程
MOV AL,[EDI] ;将字符串的字符值送入AL寄存器
CMP AL,chr ;把AL与待查找字符比较
JE print ;如果相等,找到了,跳转到打印过程
CMP AL,0 ;AL与待查找字符不想等,则与终止符比较,是否到了字符串末尾?
JE NotFound ;到达字符串末尾,未找到待查找字符,跳转到“未发现”
ADD EDI,1 ;字符串索引值+1
INC AH ;数组下标计数+1
JMP stringLocate ;继续查找
NotFound:
MOV AH,0 ;将数组下标值置零,表示未找到
print:
INVOKE crt_printf,addr format,AH ;打印
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP

END main

strcmp()

Strcmp.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
.386
.model flat, stdcall

include kernel32.inc
includelib kernel32.lib

include msvcrt.inc
includelib msvcrt.lib

.data
format db "%d", 0AH, 0
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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;strcmp逻辑
compare: ;比较过程
MOV AL,[ESI] ;取第一个字符串对应位置的字符,送入AL
MOV AH,[EDI] ;取第二个字符串对应位置的字符,送入AH
CMP AL,AH ;比较两个字符的大小
JL less ;第一个字符串小于第二个字符串,跳转
JG greater ;第一个字符串大于第二个字符串,跳转
CMP AL,0 ;字符串一对应位置字符等于字符串二对应位置字符,比较是否为终止符'\0'
JE equal ;等于终止符则两字符串相等,跳转
ADD ESI,1 ;不等于终止符则继续比较,索引值+1
ADD EDI,1 ;同上
JMP compare ;那我再比较下一个位置的字符值
;以下根据字符串比较规则对EAX(存放结果)的赋值
less:
MOV EAX,-1
JMP print
greater:
MOV EAX,1
JMP print
equal:
MOV EAX,0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print:
INVOKE crt_printf, addr format, EAX

INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP

END main

编译、链接

将放入.asm的文件夹,放进masm32的目录下。

Strlen.asm

进入到指定路径->编译 ->链接

1
2
3
4
cd C:\masm32\strlen
ml /c /coff strlen.asm
link /subsystem:console strlen.obj
strlen.exe

Strchr.asm

进入到指定路径->编译 ->链接

1
2
3
4
cd C:\masm32\strchr
ml /c /coff strchr.asm
link /subsystem:console strchr.obj
strchr.exe

strcmp.asm

进入到指定路径->编译 ->链接

1
2
3
4
cd C:\masm32\strcmp
ml /c /coff strcmp.asm
link /subsystem:console strcmp.obj
strcmp.exe

后记

编译汇编源程序

1
ml [/选项]汇编源文件列表[/link链接选项]

示例

1
ml /c /coff helloworld.asm      
选项 说明
/c (常用) 仅进行编译,不自动链接
/coff (必用) 产生的obj文件格式为coff格式
/Cp (常用) 源代码区分大小写
/Fo filename 指定输出的obj文件名
/l pathname 指定include文件的路径

链接目标文件

1
link [选项][文件列表]

示例

1
2
link /subsystem:windows helloworld.obj   (PE文件)
link /subsystem:console helloworld.obj (控制台文件)
选项 说明
/BASE: 地址 指定程序装入内存的基地址,一般PE文件默认的装入地址是0x400000处,dll文件装入0x10000000,用此选项可以修改这个默认值。
/DEBUG 在PE文件中加入调试信息。
/OUT: 文件名 指定输出文件名,默认的扩展名是.exe
/SUBSYSTEM:系统名 指定程序运行的操作系统,可以是NATIVE,WINDOWS,CONSOLE等

评论