?? 012.txt
字號:
第十二課 內存管理和文件輸入/輸出
--------------------------------------------------------------------------------
本課中我們將學習基本的內存管理和文件輸入/輸出操作方面的知識。另外我們還將用上課學的通用對話框作為我們的顯示“設備”。
理論:
從用戶的角度來看,WIN32的內存管理是非常簡單和明了的。每一個應用程序都有自己獨立的4G地址空間,這種內存模式叫做“平坦”型地址模式,所有的段寄存器或描述符都指向同樣的起始地址,所有的地址偏移都是32位的長度,這樣一個應用程序無須變換選擇符就可以存取自己的多達4G的地址空間。這種內存管理模式是非常簡潔而便于管理的,而且我們再不用和那些令人討厭的“near”和“far”指針打交道了。
在W16下有兩種主要類型的API:全局和局部。“全局”的API 分配在其他的段中,這樣從內存角度來看他們是一些“far”(遠)函數或者叫遠過程調用,“局部”API只要和進程的堆打交道,所以把它們叫做“near”(近)函數或者近過程調用。而在WIN32中,這兩種內存模式是相同的,無論您調用GlobalAlloc還是LocalAlloc,結果都是一樣。
至于分配和使用內存的過程都是一樣的:
調用GlobalAlloc函數分配一塊內存,該函數會返回分配的內存句柄。
調用GlobalLock函數鎖定內存塊,該函數接受一個內存句柄作為參數,然后返回一個指向被鎖定的內存塊的指針。
您可以用該指針來讀寫內存。
調用GlobalUnlock函數來解鎖先前被鎖定的內存,該函數使得指向內存塊的指針無效。
調用GlobalFree函數來釋放內存塊。您必須傳給該函數一個內存句柄。
在WIN32中您也可以用“Local”替代內存分配API函數帶有“Global”字樣的函數中的“Global”,也即用LocalAlloc、LocalLock等。
在調用函數GlobalAlloc時使用GMEM_FIXED標志位可以更進一步簡化操作。使用了該標志后,Global/LocalAlloc返回的是指向已分配內存的指針而不是句柄,這樣也就不用調用Global/LocalLock來鎖定內存了,釋放內存時只要直接調用Global/LocalFree就可以了。不過在本課中我們只使用傳統的方法,因為其它地方有許多的源代碼是用這種方法寫的。
WIN32的文件輸入/輸出API和DOS下的從外表上看幾乎一樣(譯者注:也許不管內部實現多么不同,可以想象所有的文件系統暴露給應用程序編寫者的接口的功能應該基本相同),不同的只是把DOS下的中斷方式處理文件輸入/輸出變成了對API函數的調用。以下是基本的步驟:
調用CreateFile函數生成一個文件,該函數可以應用在多方面,除了磁盤文件外,我們還可以用來打開通訊端口、管道、驅動程序或控制臺。如果成功的話,會返回指向文件或設備的句柄。然后可以使用該句柄去完成對文件或設備操作。
調用SetFilePointer來把文件指針移到想讀寫的地方。.
然后調用ReadFile 或 WriteFile來完成實際的讀寫。這些函數會自己處理文件和內存之間的數據傳送,這樣免得您自己去做分配內存等繁雜的瑣事。
調用CloseHandle來關閉文件。該函數接受一個先前打開的文件句柄。
內容:
下面的代碼段演示了:打開一個“打開文件”對話框,用戶可以選擇打開一個文本文件,然后在一個編輯控件中打開該文本文件的內容,另外用戶還可以編輯該文本文件的內容并選擇保存。
.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
.const
IDM_OPEN equ 1
IDM_SAVE equ 2
IDM_EXIT equ 3
MAXSIZE equ 260
MEMSIZE equ 65535
EditID equ 1 ; ID of the edit control
.data
ClassName db "Win32ASMEditClass",0
AppName db "Win32 ASM Edit",0
EditClass db "edit",0
MenuName db "FirstMenu",0
ofn OPENFILENAME <>
FilterString db "All Files",0,"*.*",0
db "Text Files",0,"*.txt",0,0
buffer db MAXSIZE dup(0)
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hwndEdit HWND ? ; Handle to the edit control
hFile HANDLE ? ; File handle
hMemory HANDLE ? ;handle to the allocated memory block
pMemory DWORD ? ;pointer to the allocated memory block
SizeReadWrite DWORD ? ; number of bytes actually read or write
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,300,200,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc uses ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_CREATE
invoke CreateWindowEx,NULL,ADDR EditClass,NULL,\
WS_VISIBLE or WS_CHILD or ES_LEFT or ES_MULTILINE or\
ES_AUTOHSCROLL or ES_AUTOVSCROLL,0,\
0,0,0,hWnd,EditID,\
hInstance,NULL
mov hwndEdit,eax
invoke SetFocus,hwndEdit
;==============================================
; Initialize the members of OPENFILENAME structure
;==============================================
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hWndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
.ELSEIF uMsg==WM_SIZE
mov eax,lParam
mov edx,eax
shr edx,16
and eax,0ffffh
invoke MoveWindow,hwndEdit,0,0,eax,edx,TRUE
.ELSEIF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.if lParam==0
.if ax==IDM_OPEN
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile,ADDR buffer,\
GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFile,eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory,eax
invoke GlobalLock,hMemory
mov pMemory,eax
invoke ReadFile,hFile,pMemory,MEMSIZE-1,ADDR SizeReadWrite,NULL
invoke SendMessage,hwndEdit,WM_SETTEXT,NULL,pMemory
invoke CloseHandle,hFile
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -