程序要求:
计算给定字符串的长度。
程序变量及寄存器注解:
sztext <----> 给定的字符串基址
EDI <----> 存放字符串基址
EAX <----> 用于长度计数
程序实现逻辑:
字符串结束时(即遇到终止符’\0’)停止计数。
每一次从字符串中取出一个字符并利用CMP指令与’\0’比较,将标志寄存器(包含ZF位)状态入栈。
给计数器EAX和索引地址EDI加一。
ZF出栈,LOOPNZ指令根据ZF位判断是否继续循环。
最后跳出循环时,给计数器EAX减一(以上逻辑将’\0’也计数的缘故)。
打印计数值。
关键语句含义讲解:
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!
程序要求:
返回给定字符串中特定字符的第一个索引下标值(从一计数)。
程序变量及寄存器注解:
sztext <----> 给定的字符串基址
chr <---->特定字符
EDI <----> 存放字符串基址
AH <----> 存储数组下标,从一开始
AL <---->存放字符串中字符副本的容器。
程序实现逻辑:
在字符串中逐一进行字符匹配,第一次匹配到特定字符,立即跳出循环返回索引下标值。若是直至最后匹配到终止符,则跳转到“未发现”模块,将AH置为零以表示未找到。
关键语句含义讲解:
;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 ;打印
程序要求:
按照字符串比较规则,比较两个字符串大小。(大于返回1,小于返回-1,等于返回0)。
程序变量及寄存器注解:
Sztext* <----> 给定的字符串*基址
ESI <----> 存放第一个字符串基址
EDI <----> 存放第二个字符串基址
AL <---->存放第一个字符串中字符副本的容器。
AH<---->存放第二个字符串中字符副本的容器。
程序实现逻辑:
两字符串依次比较相同位置的字符大小(按ASCII值比较),如果相等则循环比较下一位。如果不等则跳出比较逻辑得出结果。
特别说明字符串终止符,由于终止符的ASCII值为0,低于任何字符,所以是适用于比较逻辑的。
关键语句含义讲解:
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
程序要求:
用特定字符置换给定字符串的所有字符值。
程序变量及寄存器注解:
Sztext* <----> 给定的字符串*基址
chr <----> 特定字符
EDI <----> 存放字符串基址
AL <----> 存放chr
AH<---->存放字符串中字符副本的容器。
程序实现逻辑:
遍历给定字符串,使用AL中存放的chr替换该处字符并写入内存。
以终止符作为循环结束标志。
关键语句含义讲解:
MOV AL,chr ;将特定字符值送入AL寄存器
stringSet: ;字符串设特定值过程
MOV AH,[EDI] ;将字符串的一个字符送入AH寄存器
CMP AH,0 ;将此字符与终止符'\0'比较
JE print ;假如相等,则抵达字符串末尾,跳转打印
MOV [EDI],AL ;字符串未结束,赋值
ADD EDI,1 ;索引值+1
JMP stringSet ;继续循环此过程直至字符串结束
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print:
INVOKE crt_printf, addr szText
.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
.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
.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 ;szTextszText5
.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
.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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;strset逻辑
MOV AL,chr ;将特定字符值送入AL寄存器
stringSet: ;字符串设特定值过程
MOV AH,[EDI] ;将字符串的一个字符送入AH寄存器
CMP AH,0 ;将此字符与终止符'\0'比较
JE print ;假如相等,则抵达字符串末尾,跳转打印
MOV [EDI],AL ;字符串未结束,赋值
ADD EDI,1 ;索引值+1
JMP stringSet ;继续循环此过程直至字符串结束
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print:
INVOKE crt_printf, addr szText
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP
END main