代码 依次是主程序 优化函数的 和罗云彬大大的
程序代码:
;*************************************************************************
;By zklhp
;Email:zklhp#(#==@) QQ:493165744
;版权所有 转载请保持完整
;*************************************************************************
;MASMPlus 代码模板 - 控制台程序
.686
.MMX
.XMM
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
include advapi32.inc
include masm32.inc
include gdi32.inc
includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib advapi32.lib
includelib masm32.lib
includelib msvcrt.lib
include macro.asm
include _CmdLine.asm
include memcpy_sse2_align.asm
;C库函数挺好的
sscanf proto C hFile_IN:DWORD,lpszFormat_IN:DWORD,var_OUT:VARARG
memcpy proto C :DWORD,:DWORD,:DWORD
FUNCNUMBERS equ 7
.data?
dwBufLen dd ?
dwTimes dd ?
dwPages dd ?
lpPages dd ?
lpMemReserved dd ?
lpBufSrc dd ?
lpBufDst dd ?
szBuf db 256 dup(?)
time1 LARGE_INTEGER <>
time2 LARGE_INTEGER <>
times LARGE_INTEGER FUNCNUMBERS dup(<>)
sSysInfo SYSTEM_INFO <>
.CODE
;提权函数 不知道哪搞的
_EnablePrivilege proc szPriv:DWORD, bFlags:DWORD
LOCAL hToken:DWORD
LOCAL tkp:TOKEN_PRIVILEGES
invoke GetCurrentProcess
mov edx, eax
invoke OpenProcessToken, edx, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, addr hToken
mov ecx,szPriv
invoke LookupPrivilegeValue, NULL, ecx, addr tkp.Privileges.Luid
mov tkp.PrivilegeCount, 1
xor eax, eax
.if bFlags
mov eax, SE_PRIVILEGE_ENABLED
.endif
mov tkp.Privileges.Attributes, eax
invoke AdjustTokenPrivileges, hToken, FALSE, addr tkp, 0, 0, 0
push eax
invoke CloseHandle, hToken
pop eax
ret
_EnablePrivilege endp
;还可以自行补充类似的代码
;_lpDst _lpSrc 对应目的和源地址 _dwLen 单位字节
;这里面写的函数有些是已知或默认数据对齐的 和那些库函数比好像不公平 不过这个例子更多的是探讨大内存复制的情况 所以可以忽略不计。。
_MemCopy1 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
invoke RtlMoveMemory,edi,esi,ebx
;**********************************************************
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('RtlMoveMemory',09h,09h)
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+0] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+0],MM0 ;记得这里要改!!!
ret
_MemCopy1 endp
_MemCopy2 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
invoke memcpy,edi,esi,ebx
;**********************************************************
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('memcpy',09h,09h,09h)
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+8] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+8],MM0 ;记得这里要改!!!
ret
_MemCopy2 endp
_MemCopy3 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
mov ecx,ebx
shr ecx,2
rep movsd
;**********************************************************
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('rep movsd',09h,09h)
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+16] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+16],MM0 ;记得这里要改!!!
ret
_MemCopy3 endp
_MemCopy4 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
mov ecx,ebx
rep movsb
;**********************************************************961835
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('rep movsb',09h,09h)
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+24] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+24],MM0 ;记得这里要改!!!
ret
_MemCopy4 endp
_MemCopy5 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
invoke memcpy_sse2_align,edi,esi,ebx
;**********************************************************
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('memcpy_sse2_align',09h)
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+32] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+32],MM0 ;记得这里要改!!!
ret
_MemCopy5 endp
_MemCopy6 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
invoke memcpyMMX,edi,esi,ebx
;**********************************************************
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('memcpyMMX',09h,09h)
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+40] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+40],MM0 ;记得这里要改!!!
ret
_MemCopy6 endp
_MemCopy7 proc uses ebx esi edi _lpDst,_lpSrc,_dwLen
mov edi,_lpDst
mov esi,_lpSrc
mov ebx,_dwLen
invoke QueryPerformanceCounter,offset time1
;**********************************************************
invoke SSE_Copy_16bytes_align,edi,esi,ebx
;**********************************************************
invoke QueryPerformanceCounter,offset time2
invoke StdOut,CTXT('SSE_Copy_16bytes_align ')
mov ecx,time2.LowPart
sub ecx,time1.LowPart
mov ebx,ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),ecx
invoke StdOut,offset szBuf
lea esi,times
movq MM0,QWORD ptr [esi+48] ;记得这里要改!!!
movd MM1,ebx
paddq MM0,MM1
movq QWORD ptr [esi+48],MM0 ;记得这里要改!!!
ret
_MemCopy7 endp
START:
invoke StdOut,CTXT("by zklhp Email:zklhp#(#==@) QQ:493165744",0dh,0ah)
invoke StdOut,CTXT('Usage:')
invoke _argv,0,offset szBuf,sizeof szBuf
invoke StdOut,offset szBuf
invoke StdOut,CTXT(' 数据块长度(单位KB 即千字节) 循环次数',0dh,0ah)
invoke StdOut,CTXT('例如 console 10240 100 则分配10MB内存循环100次供测试',0dh,0ah)
invoke StdOut,CTXT('善意的提醒:测试程序强制性不高 数据块太大太小都不好 有可能出错的',0dh,0ah)
invoke StdOut,CTXT('注意:本程序需申请物理内存 需要锁定内存中页面的权限 如AllocateUserPhysicalPages有1314错误则需启用',0dh,0ah)
invoke StdOut,CTXT('具体可以看MSDN:http://msdn.(中文的)',0dh,0ah)
invoke _argc
.if eax != 3
invoke ExitProcess,-1
.endif
invoke _argv,1,offset szBuf,sizeof szBuf
invoke sscanf,offset szBuf,CTXT('%d'),offset dwBufLen
shl dwBufLen,10 ;单位字节
invoke _argv,2,offset szBuf,sizeof szBuf
invoke sscanf,offset szBuf,CTXT('%d'),offset dwTimes
invoke GetSystemInfo,offset sSysInfo
mov ecx,sSysInfo.dwPageSize
mov eax,dwBufLen
xor edx,edx
div ecx
mov dwPages,eax
mov ebx,eax
shl ebx,2
invoke _EnablePrivilege,CTXT('SeLockMemoryPrivilege'),TRUE
invoke VirtualAlloc,NULL,ebx,MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE ;记得VirtualFree
.if eax != NULL
mov lpPages,eax
.endif
;以下照抄MSDN里AWE例子程序
invoke GetCurrentProcess
mov ecx,eax
invoke AllocateUserPhysicalPages,ecx,offset dwPages,lpPages
.if eax != TRUE
invoke GetLastError
invoke wsprintf,offset szBuf,CTXT('AllocateUserPhysicalPages fail,GetLastError()=%d',0dh,0ah),eax
invoke StdOut,offset szBuf
invoke ExitProcess,-1
.endif
invoke wsprintf,offset szBuf,CTXT('Allocated only %d pages.(1 page = 4096 bytes = 4 KB)',0dh,0ah),dwPages
invoke StdOut,offset szBuf
invoke VirtualAlloc,NULL,dwBufLen,MEM_RESERVE or MEM_PHYSICAL,PAGE_READWRITE
.if eax == 0
invoke StdOut,CTXT('Cannot reserve memory.',0dh,0ah)
invoke ExitProcess,-1
.endif
mov lpMemReserved,eax
invoke MapUserPhysicalPages,lpMemReserved,dwPages,lpPages
.if eax != TRUE
invoke GetLastError
invoke wsprintf,offset szBuf,CTXT('MapUserPhysicalPages fail,GetLastError()=%d',0dh,0ah),eax
invoke StdOut,offset szBuf
invoke ExitProcess,-1
.endif
;到这里分配好了 分配的内存分两半 一半源一半目的
;根据页个数来的 也就是对齐到4K 如果是奇数就按少的来
mov eax,lpMemReserved
mov lpBufSrc,eax
mov eax,dwPages
shr eax,1
mov ecx,sSysInfo.dwPageSize
mul ecx
mov ebx,eax ;字节数 为分配内存的一半
;不会特别大。。
add eax,lpMemReserved
mov lpBufDst,eax
;可用可不用
;invoke RtlZeroMemory,lpMemReserved,ebx
mov ecx,ebx
shr ecx,10
invoke wsprintf,offset szBuf,CTXT('测试数据为两个 %d KB的物理内存进行复制 结果如下:',0dh,0ah),ecx
invoke StdOut,offset szBuf
invoke RtlZeroMemory,offset times,FUNCNUMBERS * 8
xor esi,esi
.while esi < dwTimes
;开始调用测试函数
invoke StdOut,CTXT('***********************************************************',0dh,0ah)
invoke _MemCopy1,lpBufDst,lpBufSrc,ebx
invoke _MemCopy2,lpBufDst,lpBufSrc,ebx
invoke _MemCopy3,lpBufDst,lpBufSrc,ebx
invoke _MemCopy4,lpBufDst,lpBufSrc,ebx
invoke _MemCopy5,lpBufDst,lpBufSrc,ebx
invoke _MemCopy6,lpBufDst,lpBufSrc,ebx
invoke _MemCopy7,lpBufDst,lpBufSrc,ebx
invoke StdOut,CTXT('***********************************************************',0dh,0ah)
inc esi
.endw
invoke StdOut,CTXT('平均用时(整除的 不精确)依次为:',0dh,0ah)
xor esi,esi
lea edi,times
.while esi < FUNCNUMBERS
mov eax,[edi]
mov edx,[edi+4]
mov ecx,dwTimes
div ecx
invoke wsprintf,offset szBuf,CTXT('%d MicroSecond',0dh,0ah),eax
invoke StdOut,offset szBuf
add edi,8
inc esi
.endw
;释放物理内存
invoke MapUserPhysicalPages,lpMemReserved,dwPages,NULL
.if eax != TRUE
invoke GetLastError
invoke wsprintf,offset szBuf,CTXT('MapUserPhysicalPages fail,GetLastError()=%d',0dh,0ah),eax
invoke ExitProcess,-1
.endif
invoke GetCurrentProcess
mov ecx,eax
invoke FreeUserPhysicalPages,ecx,offset dwPages,lpPages
.if eax != TRUE
invoke GetLastError
invoke wsprintf,offset szBuf,CTXT('FreeUserPhysicalPages fail,GetLastError()=%d',0dh,0ah),eax
invoke ExitProcess,-1
.endif
invoke VirtualFree,lpMemReserved,0,MEM_RELEASE
invoke VirtualFree,lpPages,0,MEM_RELEASE
invoke ExitProcess,0
end START
程序代码:
;前两个是网上找的 后面的一个用SSE2的是为了测试SSE对内存复制而定制的 和用movsb movsd的例子一样没有什么实际用处
.code
ALIGN 16
memcpy_sse2_align proc uses esi edi lpDst:DWORD,lpSrc:DWORD,nSize:DWORD
mov edi,lpDst ;dst
mov esi,lpSrc ;src
mov ecx,nSize ;count
mov eax,ecx
and eax,15 ; save the 16 unaligned bits
shr ecx,04H ; save num of double qua_dword
cmp ecx,1 ;if so few , move it as Byte
jg nextt
jmp normal_copy2
nextt:
push esi ;save addr of src
push edi
and esi,15 ;see if the src and dst addr can align
and edi,15
cmp esi,edi
jne normal_mmx ;if can't align use normal movdqu func
xor edx,edx
mov edx,16
sub edx,esi ;(16-low 16 bit of addr) get the num of up_moving Bytes
cmp eax,edx ;if the low 16 bits is too small,we must borrow from aligned bits;
jg not_add_sse2 ;now ignore eax == edx which makes eax = 0, we must deal with it before loop_down
add eax,16
dec ecx
not_add_sse2:
sub eax,edx ; eax maybe zero!
pop edi
pop esi ;now edx keep up_moving Byte count; eax keeps down_moving Byte count;
push ecx
loop_up_sse2: ;we must move some bytes before aligned_moving
mov ecx,edx
rep movsb
pop ecx
loop_fast_sse2: ;fast moving using movdqa
movdqa XMM1,[esi]
lea esi,[esi + 16]
movdqa [edi],XMM1
lea edi,[edi + 16]
dec ecx
jnz loop_fast_sse2
cmp eax, 0
jne loop_down_sse2
jmp done_align
loop_down_sse2:
mov ecx,eax
rep movsb
jmp dword ptr done_align ; done all
normal_mmx:
and esi,7
and edi,7
cmp esi,edi
jne normal_dword
xor edx,edx
mov edx,8
sub edx,esi ;(8-low 8 bit of addr) get the num of up_moving Bytes
and eax,7
cmp eax,edx ;if the low 16 bits is too small,we must borrow from aligned bits;
jg not_add_mmx ;now ignore eax == edx which makes eax = 0, we must deal with it before loop_down
add eax,16
dec ecx
not_add_mmx:
sub eax,edx ; eax maybe zero!
pop edi
pop esi ;now edx keep up_moving Byte count; eax keeps down_moving Byte count; ecx keeps fast_moving double qua_dword count
push ecx ;backup fast count
loop_up_mmx: ;we must move some bytes before aligned_moving
mov ecx,edx
rep movsb
pop ecx
loop_fast_mmx: ;fast moving using movdqa
movq MM1,[esi]
movq MM2,[esi + 8]
lea esi,[esi + 16]
movq [edi],MM1
movq [edi + 8],MM2
lea edi,[edi + 16]
dec ecx
jnz loop_fast_mmx
cmp eax, 0
jne loop_down_mmx
jmp done_align
loop_down_mmx:
mov ecx,eax
rep movsb
jmp done_align; done all
normal_dword:
and esi,3
and edi,3
cmp esi,edi
jne normal_word
xor edx,edx
mov edx,4
sub edx,esi ;(16-low 16 bit of addr) get the num of up_moving Bytes
and eax,3
shl ecx,2 ; transform it to be count of dword;
cmp eax,edx ;if the low 16 bits is too small,we must borrow from aligned bits;
jg not_add_dword ;now ignore eax == edx which makes eax = 0, we must deal with it before loop_down
add eax,4
dec ecx
not_add_dword:
sub eax,edx ; eax maybe zero!
pop edi
pop esi ;now edx keep up_moving Byte count; eax keeps down_moving Byte count; ecx keeps fast_moving double qua_dword count
push ecx;
loop_up_dword: ;we must move some bytes before aligned_moving
mov ecx,edx
rep movsb
pop ecx
loop_fast_dword: ;fast moving using movdqa
rep movsd
cmp eax, 0
je done_align
loop_down_dword:
mov ecx,eax
rep movsb
jmp done_align; done all
normal_word:
pop edi;here we deal with addr_unaligned moving;
pop esi
loop_unalign:
loop_in:
movq MM1,[esi] ;the reason not use "rep movsd" or "movdqu" is that doing the same thing movq is the fastest when addr is unaligned
movq MM2,[esi + 8]
lea esi,[esi + 16]
movq [edi],MM1
movq [edi + 8],MM2
lea edi,[edi + 16]
dec ecx
jnz loop_in
normal_copy2:
shl ecx, 4
add eax,ecx
cmp eax,0
je done_align
normal_loop2:
mov ecx,eax
rep movsb
done_align:
ret
memcpy_sse2_align endp
memcpyMMX proc uses ebx esi edi dest,src,nCopySize
mov ecx,nCopySize
mov ebx,ecx
and ebx,03fh
shr ecx,6
mov edi,dest
mov esi,src
cmp edi,esi
jz mmM2
jb mmM3
;if the memory block is to be moved forward,we start at the end of the block.
;if the memory block is to be moved backward,we start at the head of the block.
mov eax,nCopySize
lea esi,[esi+eax]
lea edi,[edi+eax]
mmM4:
or ecx,ecx
jz mmM5
mmM6:
movq MM0,[esi-8]
movq MM1,[esi-10h]
movq MM2,[esi-18h]
movq MM3,[esi-20h]
movq MM4,[esi-28h]
movq MM5,[esi-30h]
movq MM6,[esi-38h]
movq MM7,[esi-40h]
movq [edi-40h],MM7
movq [edi-38h],MM6
movq [edi-30h],MM5
movq [edi-28h],MM4
movq [edi-20h],MM3
movq [edi-18h],MM2
movq [edi-10h],MM1
movq [edi-8],MM0
sub esi,40h
sub edi,40h
loop mmM6
mmM5:
mov ecx,ebx
or ecx,ecx
jz mmM2
std
dec esi
dec edi
rep movsb
jmp mmM2
mmM3:
or ecx,ecx
jz mmM1
mmM:
movq MM0,[esi]
movq MM1,[esi+8]
movq MM2,[esi+16]
movq MM3,[esi+24]
movq MM4,[esi+32]
movq MM5,[esi+40]
movq MM6,[esi+48]
movq MM7,[esi+56]
movq [edi+56],MM7
movq [edi+48],MM6
movq [edi+40],MM5
movq [edi+32],MM4
movq [edi+24],MM3
movq [edi+16],MM2
movq [edi+8],MM1
movq [edi],MM0
add esi,64
add edi,64
loop mmM
mmM1:
mov ecx,ebx
or ecx,ecx
jz mmM2
cld
rep movsb
mmM2:
;emms
ret
memcpyMMX endp
SSE_Copy_16bytes_align proc uses esi edi lpDst:DWORD,lpSrc:DWORD,nSize:DWORD
mov ecx,nSize
shr ecx,4
@@:
movdqa XMM1,[esi]
add esi,16
movdqa [edi],XMM1
add edi,16
dec ecx
jnz @B
ret
SSE_Copy_16bytes_align endp
程序代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 罗云彬, http://asm.
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; _CmdLine.asm
; 命令行参数分析的通用子程序
; 功能:
; _argc ---> 对命令行参数进行数量统计
; _argv ---> 取某个命令行参数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CHAR_BLANK equ 20h ;定义空格
CHAR_DELI equ '"' ;定义分隔符
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 取命令行参数个数 (arg count)
; 参数个数必定大于等于 1, 参数 1 为当前执行文件名
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
_argc proc
local @dwArgc
pushad
mov @dwArgc,0
invoke GetCommandLine
mov esi,eax
cld
_argc_loop:
;********************************************************************
; 忽略参数之间的空格
;********************************************************************
lodsb
or al,al
jz _argc_end
cmp al,CHAR_BLANK
jz _argc_loop
;********************************************************************
; 一个参数开始
;********************************************************************
dec esi
inc @dwArgc
_argc_loop1:
lodsb
or al,al
jz _argc_end
cmp al,CHAR_BLANK
jz _argc_loop ;参数结束
cmp al,CHAR_DELI
jnz _argc_loop1 ;继续处理参数内容
;********************************************************************
; 如果一个参数中的一部分有空格,则用 " " 包括
;********************************************************************
@@:
lodsb
or al,al
jz _argc_end
cmp al,CHAR_DELI
jnz @B
jmp _argc_loop1
_argc_end:
popad
mov eax,@dwArgc
ret
_argc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 取指定位置的命令行参数
; argv 0 = 执行文件名
; argv 1 = 参数1 ...
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_argv proc _dwArgv,_lpReturn,_dwSize
local @dwArgv,@dwFlag
pushad
inc _dwArgv
mov @dwArgv,0
mov edi,_lpReturn
invoke GetCommandLine
mov esi,eax
cld
_argv_loop:
;********************************************************************
; 忽略参数之间的空格
;********************************************************************
lodsb
or al,al
jz _argv_end
cmp al,CHAR_BLANK
jz _argv_loop
;********************************************************************
; 一个参数开始
; 如果和要求的参数符合,则开始复制到返回缓冲区
;********************************************************************
dec esi
inc @dwArgv
mov @dwFlag,FALSE
mov eax,_dwArgv
cmp eax,@dwArgv
jnz @F
mov @dwFlag,TRUE
@@:
_argv_loop1:
lodsb
or al,al
jz _argv_end
cmp al,CHAR_BLANK
jz _argv_loop ;参数结束
cmp al,CHAR_DELI
jz _argv_loop2
cmp _dwSize,1
jle @F
cmp @dwFlag,TRUE
jne @F
stosb
dec _dwSize
@@:
jmp _argv_loop1 ;继续处理参数内容
_argv_loop2:
lodsb
or al,al
jz _argv_end
cmp al,CHAR_DELI
jz _argv_loop1
cmp _dwSize,1
jle @F
cmp @dwFlag,TRUE
jne @F
stosb
dec _dwSize
@@:
jmp _argv_loop2
_argv_end:
xor al,al
stosb
popad
ret
_argv endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>