用win32汇编语言实现以下C语言函数,
strlen()
strcmp()
strchr()
安装MASM
解压文件夹到指定盘符。
配置MASM路径
控制面板->系统和安全-> 系统 -> 高级系统设置 -> 环境变量 -> 系统变量
将masm相关路径添加到系统变量
变量名:include
变量值:%Masm32Dir%\Include;
变量名:lib
变量值:%Masm32Dir%\lib;
变量名:Masm32Dir
变量值: C:\masm32 //填入自己的masm安装路径
变量名:path
变量值:%Masm32Dir%\Bin;%Masm32Dir%;C:\Users\admin\AppData\Local\Microsoft\WindowsApps;C:\masm32\bin;
代码
strlen()
strlen.asm
.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
.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
.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
进入到指定路径->编译 ->链接
cd C:\masm32\strlen
ml /c /coff strlen.asm
link /subsystem:console strlen.obj
strlen.exe
Strchr.asm
进入到指定路径->编译 ->链接
cd C:\masm32\strchr
ml /c /coff strchr.asm
link /subsystem:console strchr.obj
strchr.exe
strcmp.asm
进入到指定路径->编译 ->链接
cd C:\masm32\strcmp
ml /c /coff strcmp.asm
link /subsystem:console strcmp.obj
strcmp.exe
后记
编译汇编源程序
ml [/选项]汇编源文件列表[/link链接选项]
示例
ml /c /coff helloworld.asm
选项 | 说明 |
---|---|
/c (常用) | 仅进行编译,不自动链接 |
/coff (必用) | 产生的obj文件格式为coff格式 |
/Cp (常用) | 源代码区分大小写 |
/Fo filename | 指定输出的obj文件名 |
/l pathname | 指定include文件的路径 |
… | … |
链接目标文件
link [选项][文件列表]
示例
link /subsystem:windows helloworld.obj (PE文件)
link /subsystem:console helloworld.obj (控制台文件)
选项 | 说明 |
---|---|
/BASE: 地址 | 指定程序装入内存的基地址,一般PE文件默认的装入地址是0x400000处,dll文件装入0x10000000,用此选项可以修改这个默认值。 |
/DEBUG | 在PE文件中加入调试信息。 |
/OUT: 文件名 | 指定输出文件名,默认的扩展名是.exe |
/SUBSYSTEM:系统名 | 指定程序运行的操作系统,可以是NATIVE,WINDOWS,CONSOLE等 |