?? lion-tut-c12.htm
字號:
<HTML>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<P align=center><FONT color=#0000ff>第十二課 內(nèi)存管理和文件輸入/輸出</FONT></P>
<HR SIZE=1>
本課中我們將學(xué)習(xí)基本的內(nèi)存管理和文件輸入/輸出操作方面的知識。另外我們還將用上課學(xué)的通用對話框作為我們的顯示“設(shè)備”。
<P><FONT color=#ff0000>理論:</FONT>
<P>從用戶的角度來看,WIN32的內(nèi)存管理是非常簡單和明了的。每一個應(yīng)用程序都有自己獨(dú)立的4G地址空間,這種內(nèi)存模式叫做“平坦”型地址模式,所有的段寄存器或描述符都指向同樣的起始地址,所有的地址偏移都是32位的長度,這樣一個應(yīng)用程序無須變換選擇符就可以存取自己的多達(dá)4G的地址空間。這種內(nèi)存管理模式是非常簡潔而便于管理的,而且我們再不用和那些令人討厭的“near”和“far”指針打交道了。<BR>
在W16下有兩種主要類型的API:全局和局部。“全局”的API 分配在其他的段中,這樣從內(nèi)存角度來看他們是一些“far”(遠(yuǎn))函數(shù)或者叫遠(yuǎn)過程調(diào)用,“局部”API只要和進(jìn)程的堆打交道,所以把它們叫做“near”(近)函數(shù)或者近過程調(diào)用。而在WIN32中,這兩種內(nèi)存模式是相同的,無論您調(diào)用GlobalAlloc還是LocalAlloc,結(jié)果都是一樣。<BR>
至于分配和使用內(nèi)存的過程都是一樣的:
<OL>
<LI>調(diào)用GlobalAlloc函數(shù)分配一塊內(nèi)存,該函數(shù)會返回分配的內(nèi)存句柄。
<LI>調(diào)用GlobalLock函數(shù)鎖定內(nèi)存塊,該函數(shù)接受一個內(nèi)存句柄作為參數(shù),然后返回一個指向被鎖定的內(nèi)存塊的指針。
<LI>您可以用該指針來讀寫內(nèi)存。
<LI>調(diào)用GlobalUnlock函數(shù)來解鎖先前被鎖定的內(nèi)存,該函數(shù)使得指向內(nèi)存塊的指針無效。
<LI>調(diào)用GlobalFree函數(shù)來釋放內(nèi)存塊。您必須傳給該函數(shù)一個內(nèi)存句柄。 </LI>
</OL>
<P>在WIN32中您也可以用“Local”替代內(nèi)存分配API函數(shù)帶有“Global”字樣的函數(shù)中的“Global”,也即用LocalAlloc、LocalLock等。<BR>
在調(diào)用函數(shù)GlobalAlloc時使用GMEM_FIXED標(biāo)志位可以更進(jìn)一步簡化操作。使用了該標(biāo)志后,Global/LocalAlloc返回的是指向已分配內(nèi)存的指針而不是句柄,這樣也就不用調(diào)用Global/LocalLock來鎖定內(nèi)存了,釋放內(nèi)存時只要直接調(diào)用Global/LocalFree就可以了。不過在本課中我們只使用傳統(tǒng)的方法,因?yàn)槠渌胤接性S多的源代碼是用這種方法寫的。</P>
<P>WIN32的文件輸入/輸出API和DOS下的從外表上看幾乎一樣(譯者注:也許不管內(nèi)部實(shí)現(xiàn)多么不同,可以想象所有的文件系統(tǒng)暴露給應(yīng)用程序編寫者的接口的功能應(yīng)該基本相同),不同的只是把DOS下的中斷方式處理文件輸入/輸出變成了對API函數(shù)的調(diào)用。以下是基本的步驟:
<BR>
<OL>
<LI>調(diào)用CreateFile函數(shù)生成一個文件,該函數(shù)可以應(yīng)用在多方面,除了磁盤文件外,我們還可以用來打開通訊端口、管道、驅(qū)動程序或控制臺。如果成功的話,會返回指向文件或設(shè)備的句柄。然后可以使用該句柄去完成對文件或設(shè)備操作。<BR>
調(diào)用SetFilePointer來把文件指針移到想讀寫的地方。.
<LI>然后調(diào)用ReadFile 或 WriteFile來完成實(shí)際的讀寫。這些函數(shù)會自己處理文件和內(nèi)存之間的數(shù)據(jù)傳送,這樣免得您自己去做分配內(nèi)存等繁雜的瑣事。
<LI>調(diào)用CloseHandle來關(guān)閉文件。該函數(shù)接受一個先前打開的文件句柄。 </LI>
</OL>
<P><FONT color=#ff0000>內(nèi)容:</FONT></P>
<P>下面的代碼段演示了:打開一個“打開文件”對話框,用戶可以選擇打開一個文本文件,然后在一個編輯控件中打開該文本文件的內(nèi)容,另外用戶還可以編輯該文本文件的內(nèi)容并選擇保存。</P>
<P><B>.386</B> <BR>
<B>.model flat,stdcall</B> <BR>
<B>option casemap:none</B> <BR>
<B>WinMain proto :DWORD,:DWORD,:DWORD,:DWORD</B> <BR>
<B>include \masm32\include\windows.inc</B> <BR>
<B>include \masm32\include\user32.inc</B> <BR>
<B>include \masm32\include\kernel32.inc</B> <BR>
<B>include \masm32\include\comdlg32.inc</B> <BR>
<B>includelib \masm32\lib\user32.lib</B> <BR>
<B>includelib \masm32\lib\kernel32.lib</B> <BR>
<B>includelib \masm32\lib\comdlg32.lib</B>
<P><B>.const</B> <BR>
<B>IDM_OPEN equ 1</B> <BR>
<B>IDM_SAVE equ 2</B> <BR>
<B>IDM_EXIT equ 3</B> <BR>
<B>MAXSIZE equ 260</B> <BR>
<B>MEMSIZE equ 65535</B>
<P><B>EditID equ 1
; ID of the edit control</B>
<P><B>.data</B> <BR>
<B>ClassName db "Win32ASMEditClass",0</B> <BR>
<B>AppName db "Win32 ASM Edit",0</B> <BR>
<B>EditClass db "edit",0</B> <BR>
<B>MenuName db "FirstMenu",0</B> <BR>
<B>ofn OPENFILENAME <></B> <BR>
<B>FilterString db "All Files",0,"*.*",0</B> <BR>
<B>
db "Text Files",0,"*.txt",0,0</B> <BR>
<B>buffer db MAXSIZE dup(0)</B>
<P><B>.data?</B> <BR>
<B>hInstance HINSTANCE ?</B> <BR>
<B>CommandLine LPSTR ?</B> <BR>
<B>hwndEdit HWND ?
; Handle to the edit control</B> <BR>
<B>hFile HANDLE ?
; File handle</B> <BR>
<B>hMemory HANDLE ?
;handle to the allocated memory block</B> <BR>
<B>pMemory DWORD ?
;pointer to the allocated memory block</B> <BR>
<B>SizeReadWrite DWORD ?
; number of bytes actually read or write</B>
<P><B>.code</B> <BR>
<B>start:</B> <BR>
<B> invoke GetModuleHandle, NULL</B> <BR>
<B> mov hInstance,eax</B> <BR>
<B> invoke GetCommandLine<BR>
mov CommandLine,eax</B> <BR>
<B> invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT</B>
<BR>
<B> invoke ExitProcess,eax</B>
<P><B>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD</B>
<BR>
<B> LOCAL wc:WNDCLASSEX</B> <BR>
<B> LOCAL msg:MSG</B> <BR>
<B> LOCAL hwnd:HWND</B> <BR>
<B> mov wc.cbSize,SIZEOF WNDCLASSEX</B> <BR>
<B> mov wc.style, CS_HREDRAW or CS_VREDRAW</B>
<BR>
<B> mov wc.lpfnWndProc, OFFSET WndProc</B> <BR>
<B> mov wc.cbClsExtra,NULL</B> <BR>
<B> mov wc.cbWndExtra,NULL</B> <BR>
<B> push hInst</B> <BR>
<B> pop wc.hInstance</B> <BR>
<B> mov wc.hbrBackground,COLOR_WINDOW+1</B> <BR>
<B> mov wc.lpszMenuName,OFFSET MenuName</B> <BR>
<B> mov wc.lpszClassName,OFFSET ClassName</B>
<BR>
<B> invoke LoadIcon,NULL,IDI_APPLICATION</B> <BR>
<B> mov wc.hIcon,eax</B> <BR>
<B> mov wc.hIconSm,eax</B> <BR>
<B> invoke LoadCursor,NULL,IDC_ARROW</B> <BR>
<B> mov wc.hCursor,eax</B> <BR>
<B> invoke RegisterClassEx, addr wc</B> <BR>
<B> invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR
AppName,\</B> <BR>
<B> WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\</B>
<BR>
<B> CW_USEDEFAULT,300,200,NULL,NULL,\</B>
<BR>
<B> hInst,NULL</B>
<BR>
<B> mov hwnd,eax</B> <BR>
<B> invoke ShowWindow, hwnd,SW_SHOWNORMAL</B> <BR>
<B> invoke UpdateWindow, hwnd</B> <BR>
<B> .WHILE TRUE</B> <BR>
<B> invoke GetMessage, ADDR msg,NULL,0,0</B>
<BR>
<B> .BREAK .IF (!eax)</B> <BR>
<B> invoke TranslateMessage, ADDR
msg</B> <BR>
<B> invoke DispatchMessage, ADDR msg</B>
<BR>
<B> .ENDW</B> <BR>
<B> mov eax,msg.wParam</B> <BR>
<B> ret</B> <BR>
<B>WinMain endp</B>
<P><B>WndProc proc uses ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</B>
<BR>
<B> .IF uMsg==WM_CREATE</B> <BR>
<B> invoke CreateWindowEx,NULL,ADDR
EditClass,NULL,\</B> <BR>
<B>
WS_VISIBLE or WS_CHILD or ES_LEFT or ES_MULTILINE or\</B> <BR>
<B>
ES_AUTOHSCROLL or ES_AUTOVSCROLL,0,\</B> <BR>
<B>
0,0,0,hWnd,EditID,\</B> <BR>
<B>
hInstance,NULL</B> <BR>
<B> mov hwndEdit,eax</B> <BR>
<B> invoke SetFocus,hwndEdit</B> <BR>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -