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

  1. strlen()

  2. strcmp()

  3. strchr()

安装MASM

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

解压文件夹到指定盘符。

配置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等

评论