本帖最后由 went 于 2021-1-9 18:50 编辑
32位汇编核心代码- ;**********************************************************************************************
- ;
- ; 字符串处理函数 Code by went
- ;
- ;**********************************************************************************************
- IFNDEF STRING_ASM
- STRING_ASM EQU 1
- .CODE
- ;**********************************************************************************************
- ;查找字符索引 从0开始
- ;[字符串指针, 要查找的字符,TRUE:查找第一个 FALSE:查找最后一个]
- ;返回值 查找返回索引,未找到返回-1
- _GetCharIndex PROC,_lpszSrc:dword,_bChar:byte,_bFirst:dword
- LOCAL _dwOffset,_dwMax
- pushad
- INVOKE lstrlen,_lpszSrc
- mov _dwMax,eax ;设置最大查找次数
- mov _dwOffset,-1 ;索引置 -1
- mov dl,_bChar ;设置查找的字符
- cmp _bFirst,FALSE
- je @rev
- mov esi,_lpszSrc ;顺序查找
- mov ecx,0 ;偏移置 0
- cld
- jmp @find
- @rev: ;倒序查找
- mov ecx,_dwMax ;偏移置 _dwMax
- mov esi,_lpszSrc
- add esi,_dwMax
- std
- @find: ;开始查找
- cmp _dwMax,0 ;字符查找完成,退出
- je @ret
- dec _dwMax ;最大查找次数 -1
- cmp byte PTR [esi],dl
- je @ok ;找到 -> ok
- cmp _bFirst,FALSE
- je @F
- inc esi
- inc ecx
- jmp @find ;顺序查找,esi +1 ,ecx +1,重复
- @@:
- dec esi
- dec ecx
- jmp @find ;倒序查找,esi -1, ecx -1,重复
- @ok:
- cmp ecx,0
- je @set
- cmp _bFirst,FALSE
- jmp @set
- inc ecx
- @set:
- mov _dwOffset,ecx ;成功,设置索引
- @ret:
- popad
- cld
- mov eax,_dwOffset
- ret
- _GetCharIndex ENDP
- ;----------------------------------------------------------------------------------------------
- ;获取子字符串
- ;[buffer指针, 源字符串指针, 开始索引(0开始), 字符串长度]
- _GetSubString PROC,_lpBuffer:dword,_lpStr:dword,_dwStartIndex:dword,_dwSubLen:dword
- pushad
- mov esi,_lpStr
- add esi,_dwStartIndex
- mov edi,_lpBuffer
- mov ecx,_dwSubLen
- rep movsb
- mov byte PTR [edi],0
- popad
- ret
- _GetSubString ENDP
- ;----------------------------------------------------------------------------------------------
- ;获取文件名,含扩展名
- ;[文件路径字符串指针,文件名buffer]
- ;返回值 EAX = 成功写入buffeer的字节数
- _GetFileName PROC,_lpszFile:dword,_lpBuffer:dword
- LOCAL _dwLen
- pushad
- mov _dwLen,0
- cmp _lpBuffer,NULL
- je @ret
- mov esi,_lpszFile
- INVOKE lstrlen,_lpszFile
- push eax
- mov ecx,eax
- add esi,eax
- std
- dec esi
- @find:
- lodsb
- cmp al,'\'
- je @done
- cmp al,'/'
- je @done
- cmp al,0
- je @done
- inc _dwLen
- jmp @find
- @done:
- cld
- add esi,2
- pop ecx
- mov edi,esi
- sub edi,_lpszFile
- sub ecx,edi
- mov edi,_lpBuffer
- rep movsb
- mov byte ptr [edi],0
- @ret:
- popad
- mov eax,_dwLen
- ret
- _GetFileName ENDP
- ;----------------------------------------------------------------------------------------------
- ;字符串编码转换
- ;[源字符串指针,源字符串编码(CP_XXX),保存转换后的字符串buffer的指针,目标字符串编码(CP_XXX),buffer长度]
- ;返回值 : EAX = 成功写入buffeer的字节数
- _ConvertString PROC,_lpszSrc:dword,_dwSrcType:dword,_lpBuffer:dword,_dwTagType:dword,_dwBufSize:dword
- LOCAL _dwWcharNum,_dwSize,_hHeap,_lpWStr
- pushad
- ;获取默认堆
- INVOKE GetProcessHeap
- mov _hHeap,eax
- ;源字符串转Unicode
- INVOKE MultiByteToWideChar,_dwSrcType,0,_lpszSrc,-1,NULL,0
- mov _dwWcharNum,eax
- mov edx,2
- mul edx
- inc eax
- mov _dwSize,eax ;获取Unicode字符串需要字节长度
- INVOKE HeapAlloc,_hHeap,HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY,_dwSize
- mov _lpWStr,eax ;为Unicode字符串申请堆内存
- ;_dwSrcType -> Unicode
- INVOKE MultiByteToWideChar,_dwSrcType,0,_lpszSrc,-1,_lpWStr,_dwSize
- ;Unicode转目标字符串
- INVOKE WideCharToMultiByte,_dwTagType,0,_lpWStr,_dwWcharNum,_lpBuffer,_dwBufSize,NULL,NULL
- mov _dwSize,eax
- ;释放堆内存
- INVOKE HeapFree,_hHeap,HEAP_NO_SERIALIZE,_lpWStr
- popad
- mov eax,_dwSize
- ret
- _ConvertString ENDP
- ;----------------------------------------------------------------------------------------------
- ;URL 编码
- ;[源字符串指针,保存转换后的字符串buffer的指针,buffer长度]
- ;[EAX = 成功写入buffeer的字节数(不含0)]
- _UrlEncoder PROC,_lpszStr:dword,_lpBuffer:dword,_dwBufSize:dword
- LOCAL _dwWcharSize,_hHeap,_dwLen
- LOCAL _lpUTF8Str,_dwUtf8Size,_buf[3]:BYTE
- pushad
- ;获取默认堆
- INVOKE GetProcessHeap
- mov _hHeap,eax
- INVOKE lstrlen,_lpszStr
- mov edx,3
- mul edx
- mov _dwUtf8Size,eax
- INVOKE HeapAlloc,_hHeap,HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY,_dwUtf8Size
- mov _lpUTF8Str,eax ;为UTF8字符串申请堆内存
- ;ANSI转UTF8
- INVOKE _ConvertString,_lpszStr,CP_ACP,_lpUTF8Str,CP_UTF8,_dwUtf8Size
- @init:
- mov _dwLen,0
- mov esi,_lpUTF8Str
- mov edi,_lpBuffer
- ;检查_dwBufSize
- cmp eax,0
- je @ret ;UTF8转换失败,退出
- dec eax
- mov edx,3
- mul edx
- inc eax
- cmp eax,_dwBufSize
- ja @ret ;长度不够,退出
- cld
- @copy:
- lodsb
- cmp al,0
- je @ret
- mov byte PTR [edi],'%' ;添加 %
- inc edi
- @@:
- movzx eax,al
- INVOKE wsprintf,ADDR _buf,$TZO('%2X'),eax
- push esi
- lea esi,_buf
- mov ecx,eax
- rep movsb ;复制十六进制数据
- pop esi
- add _dwLen,3
- jmp @copy
- @ret:
- mov byte PTR [edi],0 ;末尾加0
- popad
- mov eax,_dwLen
- ret
- _UrlEncoder ENDP
- ;----------------------------------------------------------------------------------------------
- ;URL 解码
- ;[源字符串指针,保存转换后的字符串buffer的指针,buffer长度]
- ;[EAX = 成功写入buffeer的字节数(不含0)]
- _UrlDecoder PROC,_lpszStr:dword,_lpBuffer:dword,_dwBufSize:dword
- LOCAL _dwSize,_hHeap,_lpUTF8Str
- LOCAL _buf[3]:BYTE
- pushad
- INVOKE GetProcessHeap
- mov _hHeap,eax
- INVOKE lstrlen,_lpszStr
- mov _dwSize,eax
- ;获取UTF8字符串
- INVOKE HeapAlloc,_hHeap,HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY,_dwSize
- mov _lpUTF8Str,eax ;为UTF8字符串申请堆内存
- mov esi,_lpszStr
- mov edi,_lpUTF8Str
- mov ecx,_dwSize
- cld
- mov ecx,0
- @cmp:
- lodsb
- cmp al,0 ;AL = 0 结束
- je @convert
- cmp al,'%' ;AL = '%' ?
- je @copy2 ;是 则复制2个字符到_buf
- @copy1:
- ;$PT <ENDL,'COPY 1'>
- stosb ;否 则直接复制一个字符到_buf
- jmp @cmp
- @copy2:
- cmp byte ptr [esi],0
- je @copy1 ;下个字符为0,复制AL
- cmp byte ptr [esi],'%'
- je @copy1 ;下个字符为%,复制AL
- cmp byte ptr [esi],'0'
- jl @copy1 ;下个字符 < '0',复制AL
- cmp byte ptr [esi],'9'
- jle @F ;'0' <= 下个字符 <= '9' @F
- cmp byte ptr [esi],'A'
- jl @copy1 ;'9' < 下个字符 < 'A',复制AL
- cmp byte ptr [esi],'F'
- ja @copy1 ;下个字符 > 'F',复制AL
- @@:
- cmp byte ptr [esi + 1],0
- je @copy1
- cmp byte ptr [esi + 1],'%'
- je @copy1
- cmp byte ptr [esi + 1],'0'
- jl @copy1
- cmp byte ptr [esi + 1],'9'
- jle @F
- cmp byte ptr [esi + 1],'A'
- jl @copy1
- cmp byte ptr [esi + 1],'F'
- ja @copy1 ;下下个字符 > 'F',复制AL
- @@:
- ;$PT <ENDL,'COPY 2'>
- push edi
- lea edi,_buf
- mov ecx,2
- rep movsb ;从_lpszStr复制2个字符到_buf
- mov byte ptr [edi],0
- ;$PT <ENDL,'1'>
- INVOKE _StringToInt,ADDR _buf,16 ;从_buf读取一个int数字
- ;$PT <ENDL,'2'>
- pop edi
- stosb ;int数字存储到_lpUTF8Str
- jmp @cmp
- @convert:
- ;$PT <ENDL,'CONVER'>
- mov byte PTR [edi],0
- ;UTF8转ANSI
- INVOKE _ConvertString,_lpUTF8Str,CP_UTF8,_lpBuffer,CP_ACP,_dwBufSize
- mov _dwSize,0
- cmp eax,0
- je @F
- dec eax
- mov _dwSize,eax
- jmp @close
- @@:
- mov esi,_lpBuffer
- mov byte PTR [esi],0
- @close:
- INVOKE HeapFree,_hHeap,HEAP_NO_SERIALIZE,_lpUTF8Str
- @ret:
- popad
- mov eax,_dwSize
- ret
- _UrlDecoder ENDP
- ;----------------------------------------------------------------------------------------------
- ;Base64编码
- ;[源字节数据指针,源数据长度,数据buffer指针,buffer长度]
- ;返回值 EAX=写入buffer字节数据(不含0)
- _Base64Encoder PROC,_lpData:dword,_dwSize:dword,_lpBuffer:dword,_dwBufSize:dword
- LOCAL _dwValue,_dwRet,_dwCount,_dwLast,_bKey:byte
- pushad
- @init:
- ;$PT <ENDL,'总长度: '>
- ;INVOKE _PrintDec,_dwSize
- mov eax,_dwSize
- mov edx,0
- mov ebx,3
- div ebx
- mov _dwCount,eax ;_dwCount = 3个一组,一共多少组
- mov _dwLast,edx ;_dwLast = 最后剩下多少个字节
- mov esi,_lpData
- mov _dwRet,0
- mov _dwValue,0
- mov edi,_lpBuffer
- ;$PT <ENDL,'组数(n/3): '>
- ;INVOKE _PrintDec,_dwCount
- ;$PT <' 剩下字符: '>
- ;INVOKE _PrintDec,_dwLast
- @read3:
- ;读取3个字节到_dwValue
- cmp _dwCount,0
- je @readLast
- mov ecx,3 ;字节计数
- mov edx,4 ;循环计数
- @set:
- ;$PT <ENDL,'当前组数: '>
- ;INVOKE _PrintDec,_dwCount
- ;$PT <ENDL,' 读取字符:'>
- ;INVOKE _PrintDec,ecx
- push edi
- lea edi,_dwValue
- mov eax,3
- sub eax,ecx
- add edi,eax ;保证设置到_dwValue最高位
- ;按内存顺序设置_dwValue高3个字节
- @load:
- lodsb
- mov byte ptr [edi + ecx],al
- loop @load
- ;$PT <' _dwValue: '>
- ;INVOKE _PrintDec,_dwValue
- ;$PT ' '
- ;_dwValue循环左移6位,共4次
- pop edi
- mov eax,_dwValue
- @shl:
- cmp edx,0
- je @next_group
- ;$PT <' '>
- rol eax,6
- mov bl,al
- and bl,00111111b ;高2位清零
- movzx ebx,bl
- ;INVOKE _PrintDec,ebx
- ;$PT '->'
- mov _bKey,bl ;开始判断范围,设置_bKey
- cmp bl,26
- jl @A_Z
- cmp bl,52
- jl @a_z
- cmp bl,62
- jl @0_9
- cmp bl,62
- je @62
- mov _bKey,'+'
- cmp bl,63
- je @63
- mov _bKey,0 ;超出映射表字符,填充0
- jmp @next
- @63:
- mov _bKey,'/'
- jmp @next
- @62:
- mov _bKey,'+'
- jmp @next
- @A_Z:
- sub _bKey,0
- add _bKey,'A'
- jmp @next
- @a_z:
- sub _bKey,26
- add _bKey,'a'
- jmp @next
- @0_9:
- sub _bKey,52
- add _bKey,'0'
- jmp @next
- @next:
- mov al,_bKey
- mov byte ptr [edi],al
- movzx ebx,al
- ;INVOKE _PrintDec,ebx
- inc edi
- dec edx
- inc _dwRet
- mov ebx,_dwBufSize
- dec ebx
- cmp _dwRet,ebx
- jae @zero
- jmp @shl
- @next_group:
- cmp _dwCount,-1 ;-1表示读取最后剩下的字节结束
- je @ret
- dec _dwCount
- jmp @read3
- @readLast:
- ;读取最后剩下的字节
- cmp _dwLast,0
- je @ret
- ;$PT <ENDL,'LAST '>
- ;INVOKE _PrintDec,_dwLast
- ;$PT ' '
- ;INVOKE _PrintString,esi
- mov _dwCount,-1
- mov _dwValue,0
- mov ecx,_dwLast ;字节计数
- cmp ecx,1
- jne @F
- mov edx,2 ;剩下1个字节,设置2个Base64字符
- jmp @set
- @@:
- mov edx,3 ;剩下2个字节,设置3个Base64字符
- jmp @set ;跳转到@set设置_dwNum
- @ret:
- cmp _dwLast,0
- je @zero
- mov ecx,3
- sub ecx,_dwLast
- add _dwRet,ecx
- mov esi,$TZO('===')
- rep movsb ;填充'='
- @zero:
- mov byte ptr [edi],0 ;末尾加0
- popad
- mov eax,_dwRet
- ret
- _Base64Encoder ENDP
- ;----------------------------------------------------------------------------------------------
- ;Base64解码
- ;[源base64数据指针,源数据长度,解码数据buffer指针,buffer长度]
- ;返回值 [EAX=成功写入buffeer的字节数]
- _Base64Decoder PROC,_lpData:dword,_dwSize:dword,_lpBuffer:dword,_dwBufSize:dword
- LOCAL _dwValue,_dwCount,_dwLast,_dwRet,_dwZero
- pushad
- @init:
- mov _dwZero,0 ;记录填充0的个数
- ;$PT <ENDL,'字符总数:'>
- ;INVOKE _PrintDec,_dwSize ;源数据长度
- ;$PT <ENDL,'组数(n/4): '> ;分组 4个Base64字符为1组
- mov edx,0
- mov eax,_dwSize
- mov ebx,4
- div ebx
- mov _dwCount,eax
- mov _dwLast,edx
- ;INVOKE _PrintDec,_dwCount
- ;$PT <ENDL,'剩余字符:'>
- ;INVOKE _PrintDec,_dwLast
- mov esi,_lpData
- mov edi,_lpBuffer
- mov _dwRet,0
- @read4:
- cmp _dwCount,0
- je @ret
- ;$PT <ENDL,'读取字符到EBX:'>
- mov ecx,4
- ;INVOKE _PrintDec,ecx
- mov ebx,0 ;EBX保存当前解码数据 [XXX:00000000]
- add esi,3 ;ESI指向当前位置后第4个字符
- @load:
- cmp ecx,0
- je @set
- ;$PT ' '
- mov al,byte ptr [esi] ;加载base64字符 value
- movzx eax,al
- ;INVOKE _PrintDec,eax
- ;$PT '->' ;base64字符映射 value -> key
- cmp al,'='
- je @0
- cmp al,'+'
- je @62
- cmp al,'/'
- je @63
- cmp al,'9'
- jle @0_9
- cmp al,'Z'
- jle @A_Z
- cmp al,'z'
- jle @a_z
- @0:
- mov al,0 ;非映射表字符,填充0
- inc _dwZero
- jmp @next
- @62:
- mov al,62
- jmp @next
- @63:
- mov al,63
- jmp @next
- @A_Z:
- sub al,'A'
- add al,0
- jmp @next
- @a_z:
- sub al,'a'
- add al,26
- jmp @next
- @0_9:
- sub al,'0'
- add al,52
- jmp @next
- @next:
- movzx eax,al
- ;INVOKE _PrintDec,eax
- mov bl,al ;每读取一个字符,设置到bl
- ror ebx,6 ;EBX循环右移6位,低6位->高6位
- dec ecx
- dec esi ;ESI指向上个字符
- jmp @load
- @set:
- ;$PT ' EBX:'
- ;INVOKE _PrintDec,ebx
- mov _dwValue,ebx ;当前转换的3字节数据存到_dwValue
- push esi ;ESI备份
- ;$PT ' '
- lea esi,_dwValue
- add esi,3
- mov ecx,3
- @copy:
- mov al,byte ptr [esi]
- mov byte ptr [edi],al
- dec esi
- inc edi
- inc _dwRet
- mov eax,_dwBufSize
- dec eax
- cmp _dwRet,eax
- jl @F
- pop esi ;长度超出buffer长度,堆栈平衡,退出
- jmp @ret
- @@:
- loop @copy
- pop esi
- add esi,5 ;ESI归位,指向未读取字符开始位置
- dec _dwCount
- jmp @read4
- @ret:
- mov byte ptr [edi],0 ;末尾加零
- popad
- mov eax,_dwRet ;设置返回值
- sub eax,_dwZero ;减去填充0的字节数
- ret
- _Base64Decoder ENDP
- ;----------------------------------------------------------------------------------------------
- ENDIF
复制代码
|