2005
新的一年来到了,2004年12月31号的晚上收到很多的祝福,心里很感激我的朋友们。我的培训也告一段落了。回单位后要面临正式的工作了,大嘴昨天发信息说在学校的兄弟们过得很好,他们的BOSS还请他们堕落了一晚。呵呵,好想回到学校~~~在家呆了两天觉得也没有什么意思,还是决定看看书学习一下吧。接着把内存映射文件消化掉吧。
使用内存映射文件的步骤分两步:
1 使用CreatFileMapping创建一个内存映射文件对象。
Invoke CreatFileMapping,hFile,lpFilemappingAttributes, flProtect,dwMaximumSizeHigh,/
dwMaximumSizeLow ,lpName
.if eax
mov hFileMap,eax
.endif
这个函数确定了映射文件的用途:是在磁盘文件建立内存映射文件还是在内存页面上建立进程间共享的映射。通过设置第一个参数hFile的值可以实现上面的功能。如果hFile句柄是属于一个已经打开的文件,那么映射文件就在这个文件上建立。如果想建立存在于内存文件中内存映射文件供不同进程共享,则将hFile指定为—1。
lpFilemappingAttributes:内存映射文件对象是否可以被继承。不被继承使用NULL。
flProtect: 内存映射文件的保护方式,注意要在用CreatFile函数打开文件获得hFile句柄的时候必须指定相应的标志
flProtect,dwMaximumSizeHigh/dwMaximumSizeLow::指定64位内存映射文件的长度。将这两参数设置为零,系统会自动将内存映射文件的大小调整到磁盘文件的大小。
lpName: 内存映射文件的名字。用于进程共享的时候映射文件必须起名字。
使用OpenFileMapping打开已经建立的用于进程共享的内存映射文件。
Invoke OpenFileMapping,dwDesiredAccess,bInheritHandle, lpName
.if eax
Mov hFileMap,eax
.endif
dwDesiredAccess:指定保护类型。
lpName :创建对象时使用的名字。
bInheritHandle: 继承文件的句柄。
2 创建内存映射文件的一个视图。相当于给内存映射文件分配线形地址空间,并将线形地址与文件的内容相关联。这样应用程序可以通过存取线形地址来存取文件。
Invoke MapViewOfFile,hFileMap,dwDesiredAccess,dwFileOffsetHigh,dwFileOffsetLow,/
dwNumberOfBytesToMap
.if eax
Mov ipMemory,eax
.endif
不多说了这个函数的参数很简单。
取消映射文件:invoke UnmapViewOfFile,lpMemory
关闭映射文件:invoke CloseHandle,hFileMap
吃饭喽:)下午接着来!~
哈哈,我来了~~~中午睡上一小觉真是舒服:)天气不错啊!可是不是晚上,要不然也会学着猴子说上一句:月光不错啊,清泉石上流~~~~~~~~~hiahia
补充一下:将对文件的修改立即写到磁盘上是调用这个函数实现的
Invoke FlushViewOfFile,lpMemory,dwFileSize
不知道你的思路有没有被我打乱:)现在总结一下
使用内存映射文件进行读写文件的步骤:
1. 调用CreatFile打开想要映射的文件,获得hFile
2. 调用CreatFileMapping函数生成一个建立在CreatFile函数创建的文件对象基础上的内存映射对象,得到hFileMap
3. 调用MapViewOfFile函数把整个文件的一个区域或者整个区域映射到内存中,得到指向映射到内存的第一个字节的指针lpMemory
4. 用该指针来读写文件
5. 调用UnmapViewOfFile来解除文件映射,传入参数为lpMemory
6. 调用CloseHandle来关闭内存映射文件,传入参数为hFileMap
7. 调用CloseHandle来关闭文件,传入函数为hFile
下面来看看罗云彬《Windows32汇编程序设计》中的例子:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 罗云彬,
http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; WordCount.asm
; 文件读写例子 —— 打开文本文件进行单词统计,然后创建结果文件
; 读写文件操作使用内存映射文件函数。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff WordCount.asm
; rc WordCount.rc
; Link /subsystem:windows WordCount.obj WordCount.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comdlg32.inc
includelib comdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000
DLG_MAIN equ 100
IDC_FILE equ 101
IDC_BROWSE equ 102
WORD_COUNT struct
lpLetter dd 26 dup (?)
dwCount dd ?
dwDepth dd ?
WORD_COUNT ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
hWinMain dd ?
szFileName db MAX_PATH dup (?)
szBuffer db 4096 dup (?)
stWordCount WORD_COUNT <>
dwCount dd ?
dwOption dd ?
F_COUNTING equ 00000001h
F_FILEEND equ 00000002h
.const
szFileExt db '全部文件',0,'*.*',0,0
szLogExt db '.log',0
szErrOpenFile db '无法打开文件!',0
szErrCreateFile db '无法建立记录文件!',0
szFmtWord db '%5d (%3d‰) %s',0dh,0ah,0
szSuccees db '统计成功,请查看记录文件%s',0
szSucceesCap db '统计成功',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 遍历树并输出结果
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WalkTree proc _hFile,_lpWC,_lpsz
local @dwTemp
local @szWord[52]:byte
pushad
mov esi,_lpWC
assume esi
tr WORD_COUNT
.if [esi].dwDepth && [esi].dwCount
;********************************************************************
; 计算百分比并写入log文件
;********************************************************************
mov eax,[esi].dwCount
mov ecx,1000
mul ecx
mov ecx,dwCount
.if ecx
div ecx
.else
mov eax,0
.endif
invoke wsprintf,addr szBuffer,addr szFmtWord,[esi].dwCount,eax,_lpsz
invoke lstrlen,addr szBuffer
mov ecx,eax
invoke WriteFile,_hFile,addr szBuffer,ecx,addr @dwTemp,NULL
.endif
;********************************************************************
; 如果有下层节点则递规调用
;********************************************************************
mov @dwTemp,0
.while @dwTemp < 26
mov ebx,@dwTemp
mov ebx,dword ptr [esi+ebx*4]
.if ebx
invoke lstrcpy,addr @szWord,_lpsz
invoke lstrlen,addr @szWord
lea ecx,@szWord
add ecx,eax
mov eax,@dwTemp
add al,'a'
mov word ptr [ecx],ax
invoke _WalkTree,_hFile,ebx,addr @szWord
.endif
inc @dwTemp
.endw
;********************************************************************
; 释放节点
;********************************************************************
.if [esi].dwDepth
invoke GlobalFree,esi
.endif
popad
assume esi
tr WORD_COUNT
ret
_WalkTree endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 根据数据建立树节点或增加节点计数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CountLetter proc _dwLetter
local @dwIndex
assume edi
tr WORD_COUNT
or al,20h ;转换成小写字母
.if (al >= 'a') && (al <= 'z') ;字母
;********************************************************************
; 如果是字母则按edi指针继续搜寻下一节点,找到则更新指针,
; 未找到则建立一个新的节点
;********************************************************************
sub al,'a'
movzx eax,al
.if dword ptr [edi+eax*4]
mov edi,dword ptr [edi+eax*4]
.else
mov ebx,[edi].dwDepth
.if ebx < 50
push eax
invoke GlobalAlloc,GPTR,sizeof WORD_COUNT
pop ecx
.if eax
mov dword ptr [edi+ecx*4],eax
mov edi,eax
inc ebx
mov [edi].dwDepth,ebx
.endif
.endif
.endif
.else
;********************************************************************
; 不是字母表示一个单词已结束,增加单词计数
;********************************************************************
inc [edi].dwCount
.if [edi].dwDepth
inc dwCount
.endif
mov edi,offset stWordCount
.endif
assume edi:nothing
ret
_CountLetter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CountWord proc
local @hFile,@hFileMap,@lpMemory,@dwFileSize
local @szLogFile[MAX_PATH]:byte
local @szBuffer
invoke RtlZeroMemory,addr stWordCount,sizeof stWordCount
;********************************************************************
; 打开文件
;********************************************************************
invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,/
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE
jmp _Error
.endif
mov @hFile,eax
invoke GetFileSize,@hFile,NULL
mov @dwFileSize,eax
;********************************************************************
; 建立内存映射文件并处理每个字节
;********************************************************************
invoke CreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL
.if eax
mov @hFileMap,eax
invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0
.if eax
mov @lpMemory,eax
jmp @F
.endif
invoke CloseHandle,@hFileMap
.endif
jmp _Error
@@:
xor eax,eax
mov dwCount,eax
mov esi,@lpMemory
mov edi,offset stWordCount
.while @dwFileSize
lodsb
dec @dwFileSize
invoke _CountLetter,eax
.endw
invoke _CountLetter,0
;********************************************************************
; 关闭内存映射文件
;********************************************************************
invoke UnmapViewOfFile,@lpMemory
invoke CloseHandle,@hFileMap
invoke CloseHandle,@hFile
;********************************************************************
; 输出记录文件
;********************************************************************
invoke lstrcpy,addr @szLogFile,addr szFileName
invoke lstrcat,addr @szLogFile,addr szLogExt
invoke CreateFile,addr @szLogFile,GENERIC_WRITE,FILE_SHARE_READ,/
0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
.if eax != INVALID_HANDLE_VALUE
mov @hFile,eax
mov @szBuffer,0
mov edi,offset stWordCount
invoke _WalkTree,@hFile,edi,addr @szBuffer
invoke CloseHandle,@hFile
invoke wsprintf,addr szBuffer,addr szSuccees,addr @szLogFile
invoke MessageBox,hWinMain,addr szBuffer,addr szSucceesCap,MB_OK or MB_ICONINFORMATION
.else
invoke MessageBox,hWinMain,addr szErrCreateFile,NULL,MB_OK or MB_ICONEXCLAMATION
.endif
ret
_Error:
invoke MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONEXCLAMATION
ret
_CountWord endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
local @stOpenFileName:OPENFILENAME
mov eax,wMsg
.if eax == WM_CLOSE
.if ! (dwOption & F_COUNTING)
invoke EndDialog,hWnd,NULL
.endif
;********************************************************************
.elseif eax == WM_INITDIALOG
push hWnd
pop hWinMain
invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invoke SendDlgItemMessage,hWnd,IDC_FILE,EM_SETLIMITTEXT,MAX_PATH,0
;********************************************************************
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDC_BROWSE
;********************************************************************
invoke RtlZeroMemory,addr @stOpenFileName,sizeof OPENFILENAME
mov @stOpenFileName.lStructSize,SIZEOF @stOpenFileName
mov @stOpenFileName.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
push hWinMain
pop @stOpenFileName.hwndOwner
mov @stOpenFileName.lpstrFilter,offset szFileExt
mov @stOpenFileName.lpstrFile,offset szFileName
mov @stOpenFileName.nMaxFile,MAX_PATH
invoke GetOpenFileName,addr @stOpenFileName
.if eax
invoke SetDlgItemText,hWnd,IDC_FILE,addr szFileName
.endif
;********************************************************************
.elseif ax == IDC_FILE
invoke GetDlgItemText,hWnd,IDC_FILE,addr szFileName,MAX_PATH
mov ebx,eax
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,ebx
;********************************************************************
.elseif ax == IDOK
invoke GetDlgItem,hWnd,IDC_FILE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWnd,IDC_BROWSE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,FALSE
or dwOption,F_COUNTING
call _CountWord
and dwOption,not (F_COUNTING or F_FILEEND)
invoke GetDlgItem,hWnd,IDC_FILE
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWnd,IDC_BROWSE
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,TRUE
.endif
;********************************************************************
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
本来下午是要把整个内存映射文件看完的可是一个莫名奇妙的会把什么都打乱了~!ft~吃完晚饭回来可能还要c一会,可惜不能跟学长还有老迷,b骆小黑皮豆豆们pk了。哥哥进步很快的啊:)所以先把这个发到blog上吧。
新的一年来到了,2004年12月31号的晚上收到很多的祝福,心里很感激我的朋友们。我的培训也告一段落了。回单位后要面临正式的工作了,大嘴昨天发信息说在学校的兄弟们过得很好,他们的BOSS还请他们堕落了一晚。呵呵,好想回到学校~~~在家呆了两天觉得也没有什么意思,还是决定看看书学习一下吧。接着把内存映射文件消化掉吧。
使用内存映射文件的步骤分两步:
1 使用CreatFileMapping创建一个内存映射文件对象。
Invoke CreatFileMapping,hFile,lpFilemappingAttributes, flProtect,dwMaximumSizeHigh,/
dwMaximumSizeLow ,lpName
.if eax
mov hFileMap,eax
.endif
这个函数确定了映射文件的用途:是在磁盘文件建立内存映射文件还是在内存页面上建立进程间共享的映射。通过设置第一个参数hFile的值可以实现上面的功能。如果hFile句柄是属于一个已经打开的文件,那么映射文件就在这个文件上建立。如果想建立存在于内存文件中内存映射文件供不同进程共享,则将hFile指定为—1。
lpFilemappingAttributes:内存映射文件对象是否可以被继承。不被继承使用NULL。
flProtect: 内存映射文件的保护方式,注意要在用CreatFile函数打开文件获得hFile句柄的时候必须指定相应的标志
flProtect,dwMaximumSizeHigh/dwMaximumSizeLow::指定64位内存映射文件的长度。将这两参数设置为零,系统会自动将内存映射文件的大小调整到磁盘文件的大小。
lpName: 内存映射文件的名字。用于进程共享的时候映射文件必须起名字。
使用OpenFileMapping打开已经建立的用于进程共享的内存映射文件。
Invoke OpenFileMapping,dwDesiredAccess,bInheritHandle, lpName
.if eax
Mov hFileMap,eax
.endif
dwDesiredAccess:指定保护类型。
lpName :创建对象时使用的名字。
bInheritHandle: 继承文件的句柄。
2 创建内存映射文件的一个视图。相当于给内存映射文件分配线形地址空间,并将线形地址与文件的内容相关联。这样应用程序可以通过存取线形地址来存取文件。
Invoke MapViewOfFile,hFileMap,dwDesiredAccess,dwFileOffsetHigh,dwFileOffsetLow,/
dwNumberOfBytesToMap
.if eax
Mov ipMemory,eax
.endif
不多说了这个函数的参数很简单。
取消映射文件:invoke UnmapViewOfFile,lpMemory
关闭映射文件:invoke CloseHandle,hFileMap
吃饭喽:)下午接着来!~
哈哈,我来了~~~中午睡上一小觉真是舒服:)天气不错啊!可是不是晚上,要不然也会学着猴子说上一句:月光不错啊,清泉石上流~~~~~~~~~hiahia
补充一下:将对文件的修改立即写到磁盘上是调用这个函数实现的
Invoke FlushViewOfFile,lpMemory,dwFileSize
不知道你的思路有没有被我打乱:)现在总结一下
使用内存映射文件进行读写文件的步骤:
1. 调用CreatFile打开想要映射的文件,获得hFile
2. 调用CreatFileMapping函数生成一个建立在CreatFile函数创建的文件对象基础上的内存映射对象,得到hFileMap
3. 调用MapViewOfFile函数把整个文件的一个区域或者整个区域映射到内存中,得到指向映射到内存的第一个字节的指针lpMemory
4. 用该指针来读写文件
5. 调用UnmapViewOfFile来解除文件映射,传入参数为lpMemory
6. 调用CloseHandle来关闭内存映射文件,传入参数为hFileMap
7. 调用CloseHandle来关闭文件,传入函数为hFile
下面来看看罗云彬《Windows32汇编程序设计》中的例子:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 罗云彬,

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; WordCount.asm
; 文件读写例子 —— 打开文本文件进行单词统计,然后创建结果文件
; 读写文件操作使用内存映射文件函数。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff WordCount.asm
; rc WordCount.rc
; Link /subsystem:windows WordCount.obj WordCount.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comdlg32.inc
includelib comdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000
DLG_MAIN equ 100
IDC_FILE equ 101
IDC_BROWSE equ 102
WORD_COUNT struct
lpLetter dd 26 dup (?)
dwCount dd ?
dwDepth dd ?
WORD_COUNT ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
hWinMain dd ?
szFileName db MAX_PATH dup (?)
szBuffer db 4096 dup (?)
stWordCount WORD_COUNT <>
dwCount dd ?
dwOption dd ?
F_COUNTING equ 00000001h
F_FILEEND equ 00000002h
.const
szFileExt db '全部文件',0,'*.*',0,0
szLogExt db '.log',0
szErrOpenFile db '无法打开文件!',0
szErrCreateFile db '无法建立记录文件!',0
szFmtWord db '%5d (%3d‰) %s',0dh,0ah,0
szSuccees db '统计成功,请查看记录文件%s',0
szSucceesCap db '统计成功',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 遍历树并输出结果
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WalkTree proc _hFile,_lpWC,_lpsz
local @dwTemp
local @szWord[52]:byte
pushad
mov esi,_lpWC
assume esi

.if [esi].dwDepth && [esi].dwCount
;********************************************************************
; 计算百分比并写入log文件
;********************************************************************
mov eax,[esi].dwCount
mov ecx,1000
mul ecx
mov ecx,dwCount
.if ecx
div ecx
.else
mov eax,0
.endif
invoke wsprintf,addr szBuffer,addr szFmtWord,[esi].dwCount,eax,_lpsz
invoke lstrlen,addr szBuffer
mov ecx,eax
invoke WriteFile,_hFile,addr szBuffer,ecx,addr @dwTemp,NULL
.endif
;********************************************************************
; 如果有下层节点则递规调用
;********************************************************************
mov @dwTemp,0
.while @dwTemp < 26
mov ebx,@dwTemp
mov ebx,dword ptr [esi+ebx*4]
.if ebx
invoke lstrcpy,addr @szWord,_lpsz
invoke lstrlen,addr @szWord
lea ecx,@szWord
add ecx,eax
mov eax,@dwTemp
add al,'a'
mov word ptr [ecx],ax
invoke _WalkTree,_hFile,ebx,addr @szWord
.endif
inc @dwTemp
.endw
;********************************************************************
; 释放节点
;********************************************************************
.if [esi].dwDepth
invoke GlobalFree,esi
.endif
popad
assume esi

ret
_WalkTree endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 根据数据建立树节点或增加节点计数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CountLetter proc _dwLetter
local @dwIndex
assume edi

or al,20h ;转换成小写字母
.if (al >= 'a') && (al <= 'z') ;字母
;********************************************************************
; 如果是字母则按edi指针继续搜寻下一节点,找到则更新指针,
; 未找到则建立一个新的节点
;********************************************************************
sub al,'a'
movzx eax,al
.if dword ptr [edi+eax*4]
mov edi,dword ptr [edi+eax*4]
.else
mov ebx,[edi].dwDepth
.if ebx < 50
push eax
invoke GlobalAlloc,GPTR,sizeof WORD_COUNT
pop ecx
.if eax
mov dword ptr [edi+ecx*4],eax
mov edi,eax
inc ebx
mov [edi].dwDepth,ebx
.endif
.endif
.endif
.else
;********************************************************************
; 不是字母表示一个单词已结束,增加单词计数
;********************************************************************
inc [edi].dwCount
.if [edi].dwDepth
inc dwCount
.endif
mov edi,offset stWordCount
.endif
assume edi:nothing
ret
_CountLetter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CountWord proc
local @hFile,@hFileMap,@lpMemory,@dwFileSize
local @szLogFile[MAX_PATH]:byte
local @szBuffer
invoke RtlZeroMemory,addr stWordCount,sizeof stWordCount
;********************************************************************
; 打开文件
;********************************************************************
invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,/
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE
jmp _Error
.endif
mov @hFile,eax
invoke GetFileSize,@hFile,NULL
mov @dwFileSize,eax
;********************************************************************
; 建立内存映射文件并处理每个字节
;********************************************************************
invoke CreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL
.if eax
mov @hFileMap,eax
invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0
.if eax
mov @lpMemory,eax
jmp @F
.endif
invoke CloseHandle,@hFileMap
.endif
jmp _Error
@@:
xor eax,eax
mov dwCount,eax
mov esi,@lpMemory
mov edi,offset stWordCount
.while @dwFileSize
lodsb
dec @dwFileSize
invoke _CountLetter,eax
.endw
invoke _CountLetter,0
;********************************************************************
; 关闭内存映射文件
;********************************************************************
invoke UnmapViewOfFile,@lpMemory
invoke CloseHandle,@hFileMap
invoke CloseHandle,@hFile
;********************************************************************
; 输出记录文件
;********************************************************************
invoke lstrcpy,addr @szLogFile,addr szFileName
invoke lstrcat,addr @szLogFile,addr szLogExt
invoke CreateFile,addr @szLogFile,GENERIC_WRITE,FILE_SHARE_READ,/
0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
.if eax != INVALID_HANDLE_VALUE
mov @hFile,eax
mov @szBuffer,0
mov edi,offset stWordCount
invoke _WalkTree,@hFile,edi,addr @szBuffer
invoke CloseHandle,@hFile
invoke wsprintf,addr szBuffer,addr szSuccees,addr @szLogFile
invoke MessageBox,hWinMain,addr szBuffer,addr szSucceesCap,MB_OK or MB_ICONINFORMATION
.else
invoke MessageBox,hWinMain,addr szErrCreateFile,NULL,MB_OK or MB_ICONEXCLAMATION
.endif
ret
_Error:
invoke MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONEXCLAMATION
ret
_CountWord endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
local @stOpenFileName:OPENFILENAME
mov eax,wMsg
.if eax == WM_CLOSE
.if ! (dwOption & F_COUNTING)
invoke EndDialog,hWnd,NULL
.endif
;********************************************************************
.elseif eax == WM_INITDIALOG
push hWnd
pop hWinMain
invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invoke SendDlgItemMessage,hWnd,IDC_FILE,EM_SETLIMITTEXT,MAX_PATH,0
;********************************************************************
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDC_BROWSE
;********************************************************************
invoke RtlZeroMemory,addr @stOpenFileName,sizeof OPENFILENAME
mov @stOpenFileName.lStructSize,SIZEOF @stOpenFileName
mov @stOpenFileName.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
push hWinMain
pop @stOpenFileName.hwndOwner
mov @stOpenFileName.lpstrFilter,offset szFileExt
mov @stOpenFileName.lpstrFile,offset szFileName
mov @stOpenFileName.nMaxFile,MAX_PATH
invoke GetOpenFileName,addr @stOpenFileName
.if eax
invoke SetDlgItemText,hWnd,IDC_FILE,addr szFileName
.endif
;********************************************************************
.elseif ax == IDC_FILE
invoke GetDlgItemText,hWnd,IDC_FILE,addr szFileName,MAX_PATH
mov ebx,eax
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,ebx
;********************************************************************
.elseif ax == IDOK
invoke GetDlgItem,hWnd,IDC_FILE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWnd,IDC_BROWSE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,FALSE
or dwOption,F_COUNTING
call _CountWord
and dwOption,not (F_COUNTING or F_FILEEND)
invoke GetDlgItem,hWnd,IDC_FILE
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWnd,IDC_BROWSE
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,TRUE
.endif
;********************************************************************
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
本来下午是要把整个内存映射文件看完的可是一个莫名奇妙的会把什么都打乱了~!ft~吃完晚饭回来可能还要c一会,可惜不能跟学长还有老迷,b骆小黑皮豆豆们pk了。哥哥进步很快的啊:)所以先把这个发到blog上吧。