1. Win32 控制臺(tái)程序
1). 顯示一個(gè)消息框
MessageBoxA PROTO,
hWnd:DWORD, ; handle to window (can be null)
lpText:PTR BYTE, ; 消息框內(nèi)部
lpCaption:PTR BYTE, ; 消息框標(biāo)題
uType:DWORD ; 內(nèi)容和行為
hWnd
在控制臺(tái)應(yīng)用中可以設(shè)置為NULL
lpText
為一個(gè)以空值終止的字符串指針
lpCaotion
為一個(gè)以空值終止的對(duì)話框標(biāo)題字符串指針
uType
為消息框的內(nèi)容和行為顽腾。
內(nèi)容和行為
uType參數(shù)包含一個(gè)位映射整數(shù)崔拥,它包含三種類型的選項(xiàng):要顯示的按鈕,圖標(biāo)和默認(rèn)按鈕選項(xiàng)漾月。 其中按鈕有7個(gè)常量值:MB_OK
,MB_OKCANCEL
,MB_YESNO
,MB_YESNOCANCEL
,MB_RETRYCANCEL
,MB_ABORTRETRYIGNORE
,MB_CANCELTRYCONTINUE
饲帅。默認(rèn)的按鈕
當(dāng)按下Enter
鍵的時(shí)候矛绘,可以自動(dòng)選擇默認(rèn)的按鈕。-
圖標(biāo)
四種圖片可供選擇辱匿。- 停止: MB_ICONSTOP, MB_ICONHAND, or MB_ICONERROR
- 問號(hào)標(biāo)記(?) : MB_ICONQUESTION
- 消息標(biāo)記(i): MB_ICONINFORMATION, MB_ICONASTERISK
- 警告標(biāo)記(!): MB_ICONEXCLAMATION, MB_ICONWARNING
返回值
如果MessageBoxA失敗了键痛,則返回0,否則返回用戶點(diǎn)擊的按鈕對(duì)應(yīng)的整型匾七。它們是IDABORT, IDCANCEL,IDCONTINUE, IDIGNORE, IDNO, IDOK, IDRETRY, IDTRYAGAIN, and IDYES絮短。
示例:
; 消息框
INCLUDE Irvine32.inc
.data
captionW BYTE "Warning",0
warningMsg BYTE "The current operation may take years "
BYTE "to complete.",0
captionQ BYTE "Question",0
questionMsg BYTE "A matching user account was not found."
BYTE 0dh,0ah,"Do you wish to continue?",0
captionC BYTE "Information",0
infoMsg BYTE "Select Yes to save a backup file "
BYTE "before continuing,",0dh,0ah
BYTE "or click Cancel to stop the operation",0
captionH BYTE "Cannot View User List",0
haltMsg BYTE "This operation not supported by your "
BYTE "user account.",0
.code
main PROC
; 顯示一個(gè)帶圖標(biāo)的OK按鈕
INVOKE MessageBox, NULL, ADDR warningMsg, ADDR captionW, MB_OK + MB_ICONEXCLAMATION
; 顯示一個(gè)帶問號(hào)的圖標(biāo)和Yes/No按鈕
INVOKE MessageBox, NULL, ADDR questionMsg, ADDR captionQ, MB_YESNO + MB_ICONQUESTION
; 顯示一個(gè)消息圖標(biāo)和Yes/No/Cancel按鈕
INVOKE MessageBox, NULL, ADDR infoMsg, ADDR captionC, MB_YESNOCANCEL + MB_ICONINFORMATION + MB_DEFBUTTON2
; 顯示一個(gè)停止圖標(biāo)和一個(gè)OK按鈕
INVOKE MessageBox, NULL, ADDR haltMsg, ADDR captionH, MB_OK + MB_ICONSTOP
exit
main ENDP
END
2). 控制臺(tái)輸入
- ReadConsole
ReadConsole PROTO,
hConsoleInput:HANDLE, ; input handle
lpBuffer:PTR BYTE, ; 緩沖指針
nNumberOfCharsToRead:DWORD, ; 要讀取的字符數(shù)
lpNumberOfCharsRead:PTR DWORD, ; 要讀取的字符指針
lpReserved:DWORD ; (不使用)
hConsoleInput
一個(gè)有效的控制臺(tái)輸入句柄,使用GetStdHandle函數(shù)獲取
lpBuffer
字符數(shù)組首地址
nNumberOfCharsToRead
要讀取的字符數(shù)
lpNumberOfCharsRead
要讀取的字符指針
lpReserved
保留參數(shù)
示例:
; 從控制臺(tái)讀取數(shù)據(jù)
INCLUDE Irvine32.inc
BufSize = 80
.data
buffer BYTE BufSize DUP(?), 0, 0
stdInHandle HANDLE ?
bytesRead DWORD ?
.code
main PROC
; 獲取標(biāo)準(zhǔn)輸入句柄
INVOKE GetStdHandle, STD_INPUT_HANDLE
mov stdInHandle, eax
; 等待用戶輸入
INVOKE ReadConsole, stdInHandle, ADDR buffer, BufSize, ADDR bytesRead, 0
; 顯示緩沖內(nèi)容
mov esi, OFFSET buffer
mov ecx, bytesRead
mov ebx, TYPE buffer
call DumpMem
call WaitMsg
call Crlf
exit
main ENDP
END
- 檢查錯(cuò)誤
如果Windows API 函數(shù)返回一個(gè)錯(cuò)誤值昨忆,我們可以調(diào)用GetLastError 函數(shù)來獲取更多的錯(cuò)誤信息丁频。
.data
messageId DWORD ?
.code
call GetLastError
mov messageId,eax
獲取到錯(cuò)誤碼之后,我們可以調(diào)用FormatMessage 函數(shù)獲取具體信息
FormatMessage PROTO, ; format a message
dwFlags:DWORD, ; formatting options
lpSource:DWORD, ; location of message def
dwMsgID:DWORD, ; message identifier
dwLanguageID:DWORD, ; language identifier
lpBuffer:PTR BYTE, ; ptr to buffer receiving string
nSize:DWORD, ; buffer size
va_list:DWORD ; pointer to list of arguments
其中除了lpBuffer是輸出參數(shù)邑贴,其余均為輸入?yún)?shù)席里。
dwFlags
是一個(gè)整型的格式選項(xiàng)。
lpSource
是一個(gè)消息的地址指針拢驾。
dwMsgID
是通過GetLastError獲取到的雙字整型值奖磁。
dwLanguageID
是語言標(biāo)識(shí)。如果設(shè)置為0繁疤,則消息將是用戶默認(rèn)的語言
lpBuffer
是一個(gè)以空值終止的字符串指針咖为。
nSize
是可以使用一個(gè)特殊的緩沖來獲取消息。
va_list
是格式消息字符串的指針稠腊。
示例:
.data
messageId DWORD ?
pErrorMsg DWORD ? ; points to error message
.code
call GetLastError
mov messageId,eax
INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \
FORMAT_MESSAGE_FROM_SYSTEM, NULL, messageID, 0,
ADDR pErrorMsg, 0, NULL
- WriteWindowsMsg
顯示一個(gè)最近異常信息的字符串躁染。
;----------------------------------------------------
WriteWindowsMsg PROC USES eax edx
;
; Displays a string containing the most recent error
; generated by MS-Windows.
; Receives: nothing
; Returns: nothing
;----------------------------------------------------
.data
WriteWindowsMsg_1 BYTE "Error ",0
WriteWindowsMsg_2 BYTE ": ",0
pErrorMsg DWORD ? ; points to error message
messageId DWORD ?
.code
call GetLastError
mov messageId,eax
; Display the error number.
mov edx,OFFSET WriteWindowsMsg_1
call WriteString
call WriteDec
mov edx,OFFSET WriteWindowsMsg_2
call WriteString
; Get the corresponding message string.
INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \
FORMAT_MESSAGE_FROM_SYSTEM, NULL, messageID, NULL,
ADDR pErrorMsg, NULL, NULL
; Display the error message generated by MS-Windows.
mov edx,pErrorMsg
call WriteString
; Free the error message string.
INVOKE LocalFree, pErrorMsg
ret
WriteWindowsMsg ENDP
- 單字符輸入
控制臺(tái)模式下的單字符輸入有點(diǎn)棘手。 MS-Windows為當(dāng)前安裝的鍵盤提供設(shè)備驅(qū)動(dòng)程序架忌。 按下某個(gè)鍵時(shí)褐啡,會(huì)將8位掃描碼傳輸?shù)接?jì)算機(jī)的鍵盤端口。 當(dāng)釋放密鑰時(shí)鳖昌,發(fā)送第二掃描代碼。 MSWindows使用設(shè)備驅(qū)動(dòng)程序?qū)呙璐a轉(zhuǎn)換為16位虛擬密鑰代碼低飒,這是一種由MS-Windows定義的與設(shè)備無關(guān)的值许昨,用于標(biāo)識(shí)密鑰的用途。 MS-Windows創(chuàng)建一條消息褥赊,其中包含掃描代碼糕档,虛擬密鑰代碼和其他相關(guān)信息。
在Irvine32庫(kù)中相關(guān)函數(shù)有:- ReadChar: 從鍵盤讀取一個(gè)字符的ASCII碼,返回這個(gè)字符到AL中速那。
- ReadKey: 執(zhí)行無等待鍵盤檢查俐银。如果控制臺(tái)輸入緩沖區(qū)中沒有等待鍵,則設(shè)置Zero標(biāo)志端仰。 如果找到密鑰捶惜,則清零零標(biāo)志,AL包含零或ASCII代碼荔烧。 EAX和EDX的上半部分被覆蓋吱七。
- ReadKey測(cè)試程序
; 測(cè)試ReadKey
INCLUDE Irvine32.inc
INCLUDE Macros.inc
.code
main PROC
L1:
mov eax, 10 ; 延時(shí)消息
call Delay
call ReadKey ; 等待輸入
jz L1
test ebx, CAPSLOCK_ON
jz L2
mWrite <"CapsLock is ON", 0dh, 0ah>
jmp L3
L2:
mWrite <"CapsLock is OFF", 0dh, 0ah>
L3: exit
main ENDP
main
- 獲取鍵盤狀態(tài)
可以測(cè)試各個(gè)鍵盤鍵的狀態(tài),以找出當(dāng)前按下的鍵鹤竭。
GetKeyState PROTO, nVirtKey:DWORD
示例:
; Keyboard Toggle Keys (Keybd.asm)
INCLUDE Irvine32.inc
INCLUDE Macros.inc
; GetKeyState sets bit 0 in EAX if a toggle key is
; currently on (CapsLock, NumLock, ScrollLock).
; It sets the high bit of EAX if the specified key is
; currently down.
.code
main PROC
INVOKE GetKeyState, VK_NUMLOCK
test al,1
.IF !Zero?
mWrite <"The NumLock key is ON",0dh,0ah>
.ENDIF
INVOKE GetKeyState, VK_LSHIFT
test eax,80000000h
.IF !Zero?
mWrite <"The Left Shift key is currently DOWN",0dh,0ah>
.ENDIF
exit
main ENDP
END main
3). 控制臺(tái)輸出
數(shù)據(jù)結(jié)構(gòu)
一些Win32控制臺(tái)功能使用預(yù)定義的數(shù)據(jù)結(jié)構(gòu)踊餐,包括COORD和SMALL_RECT。WriteConsole 函數(shù)
WriteConsole函數(shù)將字符串寫入當(dāng)前光標(biāo)位置的控制臺(tái)窗口臀稚,并將光標(biāo)留在最后寫入的字符之后吝岭。
WriteConsole PROTO,
hConsoleOutput:HANDLE,
lpBuffer:PTR BYTE,
nNumberOfCharsToWrite:DWORD,
lpNumberOfCharsWritten:PTR DWORD,
lpReserved:DWORD
hConsoleOutput
控制臺(tái)輸出流句柄
lpBuffer
用戶想要輸出的數(shù)組指針
nNumberOfCharsToWrite
數(shù)組長(zhǎng)度
lpNumberOfCharsWritten
指向一個(gè)整數(shù),該整數(shù)分配了函數(shù)返回時(shí)實(shí)際寫入的字節(jié)數(shù)吧寺。
lpReserved
保留參數(shù)窜管。
示例:
; 程序調(diào)用的Win32 控制臺(tái)函數(shù): GetStdHandle, ExitProcess, WriteConsole
INCLUDE Irvine32.inc
.data
endl EQU <0dh,0ah> ; end of line sequence
message LABEL BYTE
BYTE "This program is a simple demonstration of"
BYTE "console mode output, using the GetStdHandle"
BYTE "and WriteConsole functions.",endl
messageSize DWORD ($ - message)
consoleHandle HANDLE 0 ; handle to standard output device
bytesWritten DWORD ? ; number of bytes written
.code
main PROC
; 獲取控制臺(tái)輸出句柄
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov consoleHandle, eax
; 在控制臺(tái)輸出一個(gè)字符串
INVOKE WriteConsole,
consoleHandle,
ADDR message,
messageSize,
ADDR bytesWritten,
0
call WaitMsg
INVOKE ExitProcess, 0
main ENDP
END
- WriteConsoleOutputCharacter 函數(shù)
WriteConsoleOutputCharacter函數(shù)將字符數(shù)組復(fù)制到控制臺(tái)屏幕緩沖區(qū)的連續(xù)單元格,從指定位置開始撮执。
WriteConsoleOutputCharacter PROTO,
hConsoleOutput:HANDLE, ; console output handle
lpCharacter:PTR BYTE, ; pointer to buffer
nLength:DWORD, ; size of buffer
dwWriteCoord:COORD, ; first cell coordinates
lpNumberOfCharsWritten:PTR DWORD ; output count
4). 讀寫文件
- CreateFile 函數(shù)
CreateFile函數(shù)可以創(chuàng)建新文件或打開現(xiàn)有文件微峰。 如果成功,則返回打開文件的句柄; 否則抒钱,它返回一個(gè)名為INVALID_HANDLE_VALUE的特殊常量蜓肆。
CreateFile PROTO, ; create new file
lpFilename:PTR BYTE, ; ptr to filename
dwDesiredAccess:DWORD, ; access mode
dwShareMode:DWORD, ; share mode
lpSecurityAttributes:DWORD, ; ptr security attrib
dwCreationDisposition:DWORD, ; file creation options
dwFlagsAndAttributes:DWORD, ; file attributes
hTemplateFile:DWORD ; handle to template file
dwDesiredAccess: 允許您指定對(duì)文件的讀訪問,寫訪問谋币,讀/寫訪問或設(shè)備查詢?cè)L問仗扬。
dwCreationDisposition: 指定對(duì)存在的文件執(zhí)行的操作以及文件不存在時(shí)要執(zhí)行的操作。
dwFlagsAndAttributes: 除了所有其他文件屬性都覆蓋FILE_ATTRIBUTE_NORMAL之外蕾额,任何屬性組合都是可接受的早芭。
示例:
—— 讀取一個(gè)已存在的文件
INVOKE CreateFile,
ADDR filename, ; ptr to filename
GENERIC_READ, ; read from the file
DO_NOT_SHARE, ; share mode
NULL, ; ptr to security attributes
OPEN_EXISTING, ; open an existing file
FILE_ATTRIBUTE_NORMAL, ; normal file attribute
0 ; not used
—— 為已存在的文件寫內(nèi)容
INVOKE CreateFile,
ADDR filename,
GENERIC_WRITE, ; write to the file
DO_NOT_SHARE,
NULL,
OPEN_EXISTING, ; file must exist
FILE_ATTRIBUTE_NORMAL,
0
—— 創(chuàng)建一個(gè)文件,并設(shè)置普通屬性诅蝶,擦除已有的文件內(nèi)容
INVOKE CreateFile,
ADDR filename,
GENERIC_WRITE, ; write to the file
DO_NOT_SHARE,
NULL,
CREATE_ALWAYS, ; overwrite existing file
FILE_ATTRIBUTE_NORMAL,
0
—— 如果文件不存在則創(chuàng)建新文件退个,如果存在則打開
INVOKE CreateFile,
ADDR filename,
GENERIC_WRITE, ; write to the file
DO_NOT_SHARE,
NULL,
CREATE_NEW, ; don't erase existing file
FILE_ATTRIBUTE_NORMAL,
0
- CloseHandle 函數(shù)
CloseHandle函數(shù)關(guān)閉一個(gè)打開的文件句柄。
CloseHandle PROTO,
hObject:HANDLE ; handle to object
- ReadFile 函數(shù)
ReadFile函數(shù)從一個(gè)文件中讀取文本调炬。
ReadFile PROTO,
hFile:HANDLE, ; input handle
lpBuffer:PTR BYTE, ; ptr to buffer
nNumberOfBytesToRead:DWORD, ; num bytes to read
lpNumberOfBytesRead:PTR DWORD, ; bytes actually read
lpOverlapped:PTR DWORD ; ptr to asynch info
hFile
是一個(gè)CreateFile函數(shù)返回的文件句柄
lpBuffer
是從文件中接收到的數(shù)據(jù)指針
nNumberOfBytesToRead
指定從文件中讀取的最大字節(jié)數(shù)
lpNumberOfBytesRead
指向一個(gè)整數(shù)语盈,表示函數(shù)返回時(shí)實(shí)際讀取的字節(jié)數(shù)
lpOverlapped
應(yīng)該設(shè)置為NULL(0)進(jìn)行同步讀取(我們使用)缰泡。 如果函數(shù)失敗刀荒,則返回值為零。
- WriteFile 函數(shù)
WriteFile函數(shù)使用輸出句柄將數(shù)據(jù)寫入文件。 句柄可以是屏幕緩沖區(qū)句柄缠借,也可以是分配給文本文件的句柄干毅。 該函數(shù)開始在文件內(nèi)部位置指針指示的位置將數(shù)據(jù)寫入文件。 寫操作完成后泼返,文件的位置指針由實(shí)際寫入的字節(jié)數(shù)調(diào)整硝逢。
WriteFile PROTO,
hFile:HANDLE, ; output handle
lpBuffer:PTR BYTE, ; pointer to buffer
nNumberOfBytesToWrite:DWORD, ; size of buffer
lpNumberOfBytesWritten:PTR DWORD, ; num bytes written
lpOverlapped:PTR DWORD ; ptr to asynch info
hFile
是已打開文件的句柄
lpBuffer
是要寫入文件內(nèi)容指針
nNumberOfBytesToWrite
是指定寫入文件的字節(jié)數(shù)
lpNumberOfBytesWritten
是指向一個(gè)整數(shù),該整數(shù)指定函數(shù)執(zhí)行后實(shí)際寫入的字節(jié)數(shù)
lpOverlapped
對(duì)于同步操作符隙,lpOverlapped應(yīng)設(shè)置為NULL趴捅。 如果函數(shù)失敗,則返回值為零
- SetFilePointer 函數(shù)
SetFilePointer函數(shù)移動(dòng)打開文件的位置指針.
SetFilePointer PROTO,
hFile:HANDLE, ; file handle
lDistanceToMove:SDWORD, ; bytes to move pointer
lpDistanceToMoveHigh:PTR SDWORD, ; ptr bytes to move, high
dwMoveMethod:DWORD ; starting point
dwMoveMethod
移動(dòng)指針的起始位置霹疫,有三個(gè)可選常量FILE_BEGIN, FILE_CURRENT, and FILE_END拱绑。
示例:
INVOKE SetFilePointer,
fileHandle, ; file handle
0, ; distance low
0, ; distance high
FILE_END ; move method
5). Irvine32 庫(kù)中的文件I/O操作
CreateOutputFile, OpenFile, WriteToFile, ReadFromFile, and CloseFile 源碼如下:
;------------------------------------------------------
CreateOutputFile PROC
;
; Creates a new file and opens it in output mode.
; Receives: EDX points to the filename.
; Returns: If the file was created successfully, EAX
; contains a valid file handle. Otherwise, EAX
; equals INVALID_HANDLE_VALUE.
;------------------------------------------------------
INVOKE CreateFile,
edx, GENERIC_WRITE, DO_NOT_SHARE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
ret
CreateOutputFile ENDP
;------------------------------------------------------
OpenFile PROC
;
; Opens a new text file and opens for input.
; Receives: EDX points to the filename.
; Returns: If the file was opened successfully, EAX
; contains a valid file handle. Otherwise, EAX equals
; INVALID_HANDLE_VALUE.
;------------------------------------------------------
INVOKE CreateFile,
edx, GENERIC_READ, DO_NOT_SHARE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
ret
OpenFile ENDP
;--------------------------------------------------------
WriteToFile PROC
;
; Writes a buffer to an output file.
; Receives: EAX = file handle, EDX = buffer offset,
; ECX = number of bytes to write
; Returns: EAX = number of bytes written to the file.
; If the value returned in EAX is less than the
; argument passed in ECX, an error likely occurred.
;--------------------------------------------------------
.data
WriteToFile_1 DWORD ? ; number of bytes written
.code
INVOKE WriteFile, ; write buffer to file
eax, ; file handle
edx, ; buffer pointer
ecx, ; number of bytes to write
ADDR WriteToFile_1, ; number of bytes written
0 ; overlapped execution flag
mov eax,WriteToFile_1 ; return value
ret
WriteToFile ENDP
;--------------------------------------------------------
ReadFromFile PROC
;
; Reads an input file into a buffer.
; Receives: EAX = file handle, EDX = buffer offset,
; ECX = number of bytes to read
; Returns: If CF = 0, EAX = number of bytes read; if
; CF = 1, EAX contains the system error code returned
; by the GetLastError Win32 API function.
;--------------------------------------------------------
.data
ReadFromFile_1 DWORD ? ; number of bytes read
.code
INVOKE ReadFile,
eax, ; file handle
edx, ; buffer pointer
ecx, ; max bytes to read
ADDR ReadFromFile_1,; number of bytes read
0 ; overlapped execution flag
mov eax,ReadFromFile_1
ret
ReadFromFile ENDP
;--------------------------------------------------------
CloseFile PROC
;
; Closes a file using its handle as an identifier.
; Receives: EAX = file handle
; Returns: EAX = nonzero if the file is successfully
; closed.
;--------------------------------------------------------
INVOKE CloseHandle, eax
ret
CloseFile ENDP
6). 測(cè)試文件I/O程序
- 寫文件程序
; 創(chuàng)建文件, 生成的文件在項(xiàng)目的根目錄下
INCLUDE Irvine32.inc
BUFFER_SIZE = 501
.data
buffer BYTE BUFFER_SIZE DUP(?)
filename BYTE "output.txt", 0
fileHandle HANDLE ?
stringLength DWORD ?
bytesWritten DWORD ?
str1 BYTE "Cannot create file", 0dh, 0ah, 0
str2 BYTE "Bytes written to file [output.txt]: ", 0
str3 BYTE "Enter up to 500 characters and press"
BYTE "[Enter]: ", 0dh, 0ah, 0
.code
main PROC
; 創(chuàng)建一個(gè)新的文本文件
mov edx, OFFSET filename
call CreateOutputFile
mov fileHandle, eax
; 檢查錯(cuò)誤
cmp eax, INVALID_HANDLE_VALUE ; 是否有錯(cuò)誤
jne file_ok ; no: skip
mov edx, OFFSET str1 ; 顯示錯(cuò)誤
call WriteString
jmp quit
file_ok:
; 讓用戶輸入字符串
mov edx, OFFSET str3 ; "Enter up to ..."
call WriteString
mov ecx, BUFFER_SIZE ; 輸入是字符串
mov edx, OFFSET buffer
call ReadString
mov stringLength, eax ; 計(jì)算字符串的字符數(shù)
; 寫入文件
mov eax, fileHandle
mov edx, OFFSET buffer
mov ecx, stringLength
call WriteToFile
mov bytesWritten, eax ; 保存返回值
call CloseFile
; 顯示返回值
mov edx, OFFSET str2 ; Bytes written
call WriteString
mov eax, bytesWritten
call WriteDec
call Crlf
quit:
call WaitMsg
call Crlf
exit
main ENDP
END
- 讀文件程序
; 讀取文件內(nèi)容
INCLUDE Irvine32.inc
INCLUDE macros.inc
BUFFER_SIZE = 5000
.data
buffer BYTE BUFFER_SIZE DUP(?)
filename BYTE 80 DUP(0)
fileHandle HANDLE ?
.code
main PROC
; 讓用戶輸入文件名
mWrite "Enter an input filename: "
mov edx, OFFSET filename
mov ecx, SIZEOF filename
call ReadString
; 打開文件
mov edx,OFFSET filename
call OpenInputFile
mov fileHandle, eax
; 檢查錯(cuò)誤
cmp eax, INVALID_HANDLE_VALUE
jne file_ok
mWrite <"Cannot open file", 0dh, 0ah>
jmp quit
file_ok:
; 讀取文件內(nèi)容到緩沖區(qū)
mov edx, OFFSET buffer
mov ecx, BUFFER_SIZE
call ReadFromFile
jnc check_buffer_size
mWrite "Error reading file."
call WriteWindowsMsg
jmp close_file
check_buffer_size:
cmp eax, BUFFER_SIZE
jb buf_size_ok
mWrite <"Error: Buffer too small for the file", 0dh, 0ah>
jmp quit
buf_size_ok:
mov buffer[eax], 0
mWrite "File size: "
call WriteDec
call Crlf
; 顯示緩沖區(qū)內(nèi)容
mWrite <"Buffer: ", 0dh, 0ah, 0dh, 0ah>
mov edx, OFFSET buffer
call WriteString
call Crlf
close_file:
mov eax, fileHandle
call CloseFile
quit:
call WaitMsg
call Crlf
exit
main ENDP
END
7). 控制臺(tái)窗口操作
Win32 API提供了對(duì)控制臺(tái)窗口及其緩沖區(qū)的可控制.
有幾個(gè)函數(shù)會(huì)影響控制臺(tái)窗口及其相對(duì)于屏幕緩沖區(qū)的位置:
—— SetConsoleWindowInfo設(shè)置控制臺(tái)窗口相對(duì)于屏幕緩沖區(qū)的大小和位置。
—— GetConsoleScreenBufferInfo返回控制臺(tái)窗口相對(duì)于屏幕緩沖區(qū)的矩形坐標(biāo)(以及其他內(nèi)容)丽蝎。
—— SetConsoleCursorPosition將光標(biāo)位置設(shè)置為屏幕緩沖區(qū)內(nèi)的任何位置; 如果該區(qū)域不可見猎拨,則移動(dòng)控制臺(tái)窗口以使光標(biāo)可見。
—— ScrollConsoleScreenBuffer移動(dòng)屏幕緩沖區(qū)中的部分或全部文本屠阻,這會(huì)影響控制臺(tái)窗口中顯示的文本
- SetConsoleTitle 函數(shù)
SetConsoleTitle函數(shù)可讓我們改變控制他窗口的標(biāo)題红省。
.data
titleStr BYTE "Console title",0
.code
INVOKE SetConsoleTitle, ADDR titleStr
- GetConsoleScreenBufferInfo 函數(shù)
GetConsoleScreenBufferInfo函數(shù)返回控制臺(tái)窗口的當(dāng)前狀態(tài)信息。 它有量參數(shù):一個(gè)是控制臺(tái)窗口句柄国觉,另一個(gè)是指向由函數(shù)填充的結(jié)構(gòu)的指針吧恃。
GetConsoleScreenBufferInfo PROTO,
hConsoleOutput:HANDLE,
lpConsoleScreenBufferInfo:PTR CONSOLE_SCREEN_BUFFER_INFO
其中CONSOLE_SCREEN_BUFFER_INFO結(jié)構(gòu)體定義內(nèi)容為:
CONSOLE_SCREEN_BUFFER_INFO STRUCT
dwSize COORD <>
dwCursorPosition COORD <>
wAttributes WORD ?
srWindow SMALL_RECT <>
dwMaximumWindowSize COORD <>
CONSOLE_SCREEN_BUFFER_INFO ENDS
示例:
.data
consoleInfo CONSOLE_SCREEN_BUFFER_INFO <>
outHandle HANDLE ?
.code
INVOKE GetConsoleScreenBufferInfo, outHandle, ADDR consoleInfo
- setConsoleWindowInfo 函數(shù)
SetConsoleWindowInfo函數(shù)允許您設(shè)置控制臺(tái)窗口相對(duì)于其屏幕緩沖區(qū)的大小和位置。
SetConsoleWindowInfo PROTO,
hConsoleOutput:HANDLE, ; screen buffer handle
bAbsolute:DWORD, ; coordinate type
lpConsoleWindow:PTR SMALL_RECT ; ptr to window rectangle
bAbsolute指示如何使用lpConsoleWindow指向的結(jié)構(gòu)中的坐標(biāo)麻诀。 如果bAbsolute為true痕寓,則坐標(biāo)指定控制臺(tái)窗口的新左上角和右下角。 如果bAbsolute為false蝇闭,則坐標(biāo)將添加到當(dāng)前窗口坐標(biāo)呻率。
; 滾動(dòng)控制臺(tái)窗口
INCLUDE Irvine32.inc
.data
message BYTE ": This line of text was written "
BYTE "to the screen buffer",0dh,0ah
messageSize DWORD ($-message)
outHandle HANDLE 0 ; standard output handle
bytesWritten DWORD ? ; number of bytes written
lineNum DWORD 0
windowRect SMALL_RECT <0,0,60,11> ; left,top,right,bottom
.code
main PROC
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov outHandle,eax
.REPEAT
mov eax,lineNum
call WriteDec ; display each line number
INVOKE WriteConsole, outHandle, ; console output handle
ADDR message, ; string pointer
messageSize, ; string length
ADDR bytesWritten, ; returns num bytes written
0 ; not used
inc lineNum ; next line number
.UNTIL lineNum > 50
; Resize and reposition the console window relative to the
; screen buffer.
INVOKE SetConsoleWindowInfo,
outHandle,
TRUE,
ADDR windowRect ; window rectangle
call Readchar ; wait for a key
call Clrscr ; clear the screen buffer
call Readchar ; wait for a second key
INVOKE ExitProcess,0
main ENDP
END main
main ENDP
END
- SetConsoleScreenBufferSize 函數(shù)
SetConsoleScreenBufferSize函數(shù)允許您將屏幕緩沖區(qū)大小設(shè)置為X列Y行。
SetConsoleScreenBufferSize PROTO,
hConsoleOutput:HANDLE, ; handle to screen buffer
dwSize:COORD ; new screen buffer size
8). 控制光標(biāo)
Win32 API提供了設(shè)置光標(biāo)大小呻引,可見性和屏幕位置的功能礼仗。 與這些函數(shù)相關(guān)的重要數(shù)據(jù)結(jié)構(gòu)是CONSOLE_CURSOR_INFO,其中包含有關(guān)控制臺(tái)光標(biāo)大小和可見性的信息逻悠。
CONSOLE_CURSOR_INFO STRUCT
dwSize DWORD ?
bVisible DWORD ?
CONSOLE_CURSOR_INFO ENDS
dwSize是光標(biāo)填充的字符單元格的百分比(1到100)元践。 如果光標(biāo)可見,則bVisible等于TRUE(1)童谒。
- GetConsoleCursorInfo 函數(shù)
GetConsoleCursorInfo 函數(shù)返回光標(biāo)的可見性和大小单旁。
GetConsoleCursorInfo PROTO,
hConsoleOutput:HANDLE,
lpConsoleCursorInfo:PTR CONSOLE_CURSOR_INFO
- SetConsoleCursorInfo 函數(shù)
SetConsoleCursorInfo 函數(shù)設(shè)置光標(biāo)的可見與大小。
SetConsoleCursorInfo PROTO,
hConsoleOutput:HANDLE,
lpConsoleCursorInfo:PTR CONSOLE_CURSOR_INFO
- SetConsoleCursorPosition 函數(shù)
SetConsoleCursorPosition 函數(shù)設(shè)置光標(biāo)的位置惠啄。
SetConsoleCursorPosition PROTO,
hConsoleOutput:DWORD, ; input mode handle
dwCursorPosition:COORD ; screen X,Y coordinates
9). 控制字體顏色
- SetConsoleTextAttribute 函數(shù)
SetConsoleTextAttribute 函數(shù)允許您將所有后續(xù)文本輸出的前景色和背景色設(shè)置到控制臺(tái)窗口.
SetConsoleTextAttribute PROTO,
hConsoleOutput:HANDLE, ; console output handle
wAttributes:WORD ; color attribute
- WriteConsoleOutputAttribute 函數(shù)
WriteConsoleOutputAttribute 函數(shù)從指定位置開始,將一組屬性值復(fù)制到控制臺(tái)屏幕緩沖區(qū)的連續(xù)單元格。
WriteConsoleOutputAttribute PROTO,
hConsoleOutput:DWORD, ; output handle
lpAttribute:PTR WORD, ; write attributes
nLength:DWORD, ; number of cells
dwWriteCoord:COORD, ; first cell coordinates
lpNumberOfAttrsWritten:PTR DWORD ; output count
lpAttribute
指向一個(gè)屬性數(shù)組撵渡,其中每個(gè)屬性的低位字節(jié)包含顏色
nLength
是數(shù)組的長(zhǎng)度
dwWriteCoord
是接收屬性的起始屏幕單元格
lpNumberOfAttrsWritten
指向一個(gè)變量融柬,該變量將保存寫入的單元格數(shù)
; 更改文本顏色
INCLUDE Irvine32.inc
.data
outHandle HANDLE ?
cellsWritten DWORD ?
xyPos COORD <10,2>
; Array of character codes:
buffer BYTE 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
BYTE 16,17,18,19,20
BufSize DWORD ($-buffer)
; Array of attributes:
attributes WORD 0Fh,0Eh,0Dh,0Ch,0Bh,0Ah,9,8,7,6
WORD 5,4,3,2,1,0F0h,0E0h,0D0h,0C0h,0B0h
.code
main PROC
; Get the Console standard output handle:
INVOKE GetStdHandle,STD_OUTPUT_HANDLE
mov outHandle,eax
; Set the colors of adjacent cells:
INVOKE WriteConsoleOutputAttribute,
outHandle, ADDR attributes,
BufSize, xyPos, ADDR cellsWritten
; Write character codes 1 through 20:
INVOKE WriteConsoleOutputCharacter,
outHandle, ADDR buffer, BufSize,
xyPos, ADDR cellsWritten
INVOKE ExitProcess,0 ; end program
main ENDP
END
10). 時(shí)間和日期函數(shù)
Win32 API提供了相當(dāng)多的時(shí)間和日期函數(shù)選擇。
- SYSTEMTIME 結(jié)構(gòu)體
SYSTEMTIME STRUCT
wYear WORD ? ; year (4 digits)
wMonth WORD ? ; month (1-12)
wDayOfWeek WORD ? ; day of week (0-6)
wDay WORD ? ; day (1-31)
wHour WORD ? ; hours (0-23)
wMinute WORD ? ; minutes (0-59)
wSecond WORD ? ; seconds (0-59)
wMilliseconds WORD ?; milliseconds (0-999)
SYSTEMTIME ENDS
wDayOfWeek 里Sunday為0趋距,然后遞加粒氧。
- GetLocalTime 和 SetLocalTime 函數(shù)
GetLocalTime函數(shù)根據(jù)系統(tǒng)時(shí)鐘返回日期和當(dāng)前時(shí)間。SetLocalTime函數(shù)設(shè)置系統(tǒng)的本地日期和時(shí)間节腐。
GetLocalTime PROTO,
lpSystemTime:PTR SYSTEMTIME
SetLocalTime PROTO,
lpSystemTime:PTR SYSTEMTIME
示例:
.data
sysTime SYSTEMTIME <>
.code
INVOKE GetLocalTime, ADDR sysTime
- GetTickCount 函數(shù)
GetTickCount函數(shù)返回自系統(tǒng)啟動(dòng)以來經(jīng)過的毫秒數(shù)外盯。
GetTickCount PROTO ; return value in EAX
示例: 計(jì)算經(jīng)過時(shí)間
; 計(jì)算經(jīng)過時(shí)間
INCLUDE Irvine32.inc
INCLUDE macros.inc
.data
startTime DWORD ?
.code
main PROC
INVOKE GetTickCount ; get starting tick count
mov startTime,eax ; save it
; Create a useless calculation loop.
mov ecx,10000100h
L1:
imul ebx
imul ebx
imul ebx
loop L1
INVOKE GetTickCount ; get new tick count
cmp eax,startTime ; lower than starting one?
jb error ; it wrapped around
sub eax,startTime ; get elapsed milliseconds
call WriteDec ; display it
mWrite <" milliseconds have elapsed",0dh,0ah>
jmp quit
error:
mWrite "Error: GetTickCount invalid--system has"
mWrite <"been active for more than 49.7 days",0dh,0ah>
quit:
call WaitMsg
call Crlf
exit
main ENDP
END main
- Sleep 函數(shù)
程序有時(shí)需要暫停或延遲很短的時(shí)間翼雀。 雖然可以構(gòu)建一個(gè)計(jì)算循環(huán)或繁忙循環(huán)來保持處理器忙饱苟,但循環(huán)的執(zhí)行時(shí)間會(huì)因處理器而異。 此外狼渊,繁忙的循環(huán)將不必要地占用處理器箱熬,從而減慢同時(shí)執(zhí)行的其他程序的速度。
Sleep PROTO,
dwMilliseconds:DWORD
- GetDateTime 程序
Irvine32庫(kù)中的GetDateTime過程返回自1601年1月1日以來經(jīng)過的100納秒時(shí)間間隔的數(shù)量狈邑。
;--------------------------------------------------
GetDateTime PROC,
pStartTime:PTR QWORD
LOCAL sysTime:SYSTEMTIME, flTime:FILETIME
;
; Gets and saves the current local date/time as a
; 64-bit integer (in the Win32 FILETIME format).
;--------------------------------------------------
; Get the system local time
INVOKE GetLocalTime,
ADDR sysTime
; Convert the SYSTEMTIME to FILETIME
INVOKE SystemTimeToFileTime,
ADDR sysTime,
ADDR flTime
; Copy the FILETIME to a 64-bit integer
mov esi,pStartTime
mov eax,flTime.loDateTime
mov DWORD PTR [esi],eax
mov eax,flTime.hiDateTime
mov DWORD PTR [esi+4],eax
ret
GetDateTime ENDP
2. Windows 圖形應(yīng)用
Win32 圖形應(yīng)用需要的文件如下圖, 使用/SUBSYSTEM:WINDOWS
替換/SUBSYSTEM:CONSOLE
(修改方法:在解決方法管理器中城须,項(xiàng)目名上右鍵 -> 屬性 -> 配置屬性 -> 鏈接器 -> 系統(tǒng) -> 子系統(tǒng),屬性 -> 配置屬性 -> 鏈接器 -> 高級(jí) -> 入口點(diǎn)main@0 改為WinMain@0)
1). 必要的結(jié)構(gòu)
- POINT 結(jié)構(gòu)體
POINT結(jié)構(gòu)指定屏幕上某點(diǎn)的X和Y坐標(biāo)米苹,以像素為單位糕伐。
POINT STRUCT
ptX DWORD ?
ptY DWORD ?
POINT ENDS
- RECT 結(jié)構(gòu)體
RECT結(jié)構(gòu)定義矩形的邊界。 左側(cè)成員包含矩形左側(cè)的X坐標(biāo)蘸嘶。 頂部成員包含矩形頂部的Y坐標(biāo)良瞧。
RECT STRUCT
left DWORD ?
top DWORD ?
right DWORD ?
bottom DWORD ?
RECT ENDS
- MSGStruct 結(jié)構(gòu)體
MSGStruct結(jié)構(gòu)定義了MS-Windows消息所需的數(shù)據(jù)。
MSGStruct STRUCT
msgWnd DWORD ?
msgMessage DWORD ?
msgWparam DWORD ?
msgLparam DWORD ?
msgTime DWORD ?
msgPt POINT <>
MSGStruct ENDS
- WNDCLASS結(jié)構(gòu)體
WNDCLASS結(jié)構(gòu)定義了一個(gè)窗口類亏较。 程序中的每個(gè)窗口都必須屬于一個(gè)類莺褒,每個(gè)程序必須為其主窗口定義一個(gè)窗口類。
WNDCLASS STRUC
style DWORD ? ; window style options
lpfnWndProc DWORD ? ; pointer to WinProc function
cbClsExtra DWORD ? ; shared memory
cbWndExtra DWORD ? ; number of extra bytes
hInstance DWORD ? ; handle to current program
hIcon DWORD ? ; handle to icon
hCursor DWORD ? ; handle to cursor
hbrBackground DWORD ? ; handle to background brush
lpszMenuName DWORD ? ; pointer to menu name
lpszClassName DWORD ? ; pointer to WinClass name
WNDCLASS ENDS
2). WinMain 程序
每個(gè)Windows應(yīng)用程序都需要一個(gè)啟動(dòng)過程雪情,通常名為WinMain遵岩,它負(fù)責(zé)以下任務(wù):
?獲取當(dāng)前程序的句柄。
?加載程序的圖標(biāo)和鼠標(biāo)光標(biāo)巡通。
?注冊(cè)程序的主窗口類尘执,并確定將處理窗口事件消息的過程。
?創(chuàng)建主窗口宴凉。
?顯示和更新主窗口誊锭。
?開始接收和發(fā)送消息的循環(huán)。 循環(huán)繼續(xù)弥锄,直到用戶關(guān)閉應(yīng)用程序窗口丧靡。
3). WinProc 程序
WinProc過程接收并處理與窗口有關(guān)的所有事件消息蟆沫。 大多數(shù)事件由用戶通過單擊并拖動(dòng)鼠標(biāo),按鍵盤鍵等啟動(dòng)温治。
WinProc PROC,
hWnd:DWORD, ; handle to the window
localMsg:DWORD, ; message ID
wParam:DWORD, ; parameter 1 (varies)
lParam:DWORD ; parameter 2 (varies)
WinProc 中的三種特殊消息:
?WM_LBUTTONDOWN饭庞,用戶按下鼠標(biāo)左鍵時(shí)生成
?WM_CREATE,表示剛剛創(chuàng)建了主窗口
?WM_CLOSE熬荆,表示應(yīng)用程序的主窗口即將關(guān)閉
4). ErrorHandler 程序
如果系統(tǒng)在注冊(cè)和創(chuàng)建程序主窗口期間報(bào)告錯(cuò)誤舟山,則會(huì)調(diào)用ErrorHandler過程(可選)。
ErrorHandler過程有幾個(gè)重要的任務(wù)要執(zhí)行:
?調(diào)用GetLastError以檢索系統(tǒng)錯(cuò)誤號(hào)卤恳。
?調(diào)用FormatMessage以檢索適當(dāng)?shù)南到y(tǒng)格式錯(cuò)誤消息字符串累盗。
?調(diào)用MessageBox以顯示包含錯(cuò)誤消息字符串的彈出消息框。
?調(diào)用LocalFree以釋放錯(cuò)誤消息字符串使用的內(nèi)存突琳。
5). 程序示例
; Windows Application (WinApp.asm)
; This program displays a resizable application window and
; several popup message boxes. Special thanks to Tom Joyce
; for the first version of this program.
INCLUDE Irvine32.inc
INCLUDE GraphWin.inc
;==================== DATA =======================
.data
AppLoadMsgTitle BYTE "Application Loaded",0
AppLoadMsgText BYTE "This window displays when the WM_CREATE "
BYTE "message is received",0
PopupTitle BYTE "Popup Window",0
PopupText BYTE "This window was activated by a "
BYTE "WM_LBUTTONDOWN message",0
GreetTitle BYTE "Main Window Active",0
GreetText BYTE "This window is shown immediately after "
BYTE "CreateWindow and UpdateWindow are called.",0
CloseMsg BYTE "WM_CLOSE message received",0
ErrorTitle BYTE "Error",0
WindowName BYTE "ASM Windows App",0
className BYTE "ASMWin",0
; Define the Application's Window class structure.
MainWin WNDCLASS <NULL,WinProc,NULL,NULL,NULL,NULL,NULL, \
COLOR_WINDOW,NULL,className>
msg MSGStruct <>
winRect RECT <>
hMainWnd DWORD ?
hInstance DWORD ?
;=================== CODE =========================
.code
WinMain PROC
; Get a handle to the current process.
INVOKE GetModuleHandle, NULL
mov hInstance, eax
mov MainWin.hInstance, eax
; Load the program's icon and cursor.
INVOKE LoadIcon, NULL, IDI_APPLICATION
mov MainWin.hIcon, eax
INVOKE LoadCursor, NULL, IDC_ARROW
mov MainWin.hCursor, eax
; Register the window class.
INVOKE RegisterClass, ADDR MainWin
.IF eax == 0
call ErrorHandler
jmp Exit_Program
.ENDIF
; Create the application's main window.
INVOKE CreateWindowEx, 0, ADDR className,
ADDR WindowName,MAIN_WINDOW_STYLE,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,NULL,NULL,hInstance,NULL
; If CreateWindowEx failed, display a message and exit.
.IF eax == 0
call ErrorHandler
jmp Exit_Program
.ENDIF
; Save the window handle, show and draw the window.
mov hMainWnd,eax
INVOKE ShowWindow, hMainWnd, SW_SHOW
INVOKE UpdateWindow, hMainWnd
; Display a greeting message.
INVOKE MessageBox, hMainWnd, ADDR GreetText,
ADDR GreetTitle, MB_OK
; Begin the program's continuous message-handling loop.
Message_Loop:
; Get next message from the queue.
INVOKE GetMessage, ADDR msg, NULL,NULL,NULL
; Quit if no more messages.
.IF eax == 0
jmp Exit_Program
.ENDIF
; Relay the message to the program's WinProc.
INVOKE DispatchMessage, ADDR msg
jmp Message_Loop
Exit_Program:
INVOKE ExitProcess,0
WinMain ENDP
;-----------------------------------------------------
WinProc PROC,
hWnd:DWORD, localMsg:DWORD, wParam:DWORD, lParam:DWORD
;
; The application's message handler, which handles
; application-specific messages. All other messages
; are forwarded to the default Windows message
; handler.
;-----------------------------------------------------
mov eax, localMsg
.IF eax == WM_LBUTTONDOWN ; mouse button?
INVOKE MessageBox, hWnd, ADDR PopupText,
ADDR PopupTitle, MB_OK
jmp WinProcExit
.ELSEIF eax == WM_CREATE ; create window?
INVOKE MessageBox, hWnd, ADDR AppLoadMsgText,
ADDR AppLoadMsgTitle, MB_OK
jmp WinProcExit
.ELSEIF eax == WM_CLOSE ; close window?
INVOKE MessageBox, hWnd, ADDR CloseMsg,
ADDR WindowName, MB_OK
INVOKE PostQuitMessage,0
jmp WinProcExit
.ELSE ; other message?
INVOKE DefWindowProc, hWnd, localMsg, wParam, lParam
jmp WinProcExit
.ENDIF
WinProcExit:
ret
WinProc ENDP
;---------------------------------------------------
ErrorHandler PROC
; Display the appropriate system error message.
;---------------------------------------------------
.data
pErrorMsg DWORD ? ; ptr to error message
messageID DWORD ?
.code
INVOKE GetLastError ; Returns message ID in EAX
mov messageID,eax
; Get the corresponding message string.
INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \
FORMAT_MESSAGE_FROM_SYSTEM,NULL,messageID,NULL,
ADDR pErrorMsg,NULL,NULL
; Display the error message.
INVOKE MessageBox,NULL, pErrorMsg, ADDR ErrorTitle,
MB_ICONERROR+MB_OK
; Free the error message string.
INVOKE LocalFree, pErrorMsg
ret
ErrorHandler ENDP
END WinMain
3. 動(dòng)態(tài)申請(qǐng)內(nèi)存
動(dòng)態(tài)內(nèi)存分配(也稱為堆分配)是一種編程語言用于在創(chuàng)建對(duì)象若债,數(shù)組和其他結(jié)構(gòu)時(shí)保留內(nèi)存的技術(shù)。
C本今,C ++和Java具有內(nèi)置的運(yùn)行時(shí)堆管理器拆座,用于處理存儲(chǔ)分配和釋放的編程請(qǐng)求。 堆啟動(dòng)管理器通常在程序啟動(dòng)時(shí)從操作系統(tǒng)分配大塊內(nèi)存冠息。 他們創(chuàng)建了一個(gè)指向存儲(chǔ)塊的免費(fèi)指針列表挪凑。 當(dāng)收到分配請(qǐng)求時(shí),堆管理器將適當(dāng)大小的內(nèi)存塊標(biāo)記為保留逛艰,并返回指向該塊的指針躏碳。 稍后,當(dāng)收到對(duì)同一塊的刪除請(qǐng)求時(shí)散怖,堆會(huì)釋放該塊菇绵,并將其返回到空閑列表。 每次收到新的分配請(qǐng)求時(shí)镇眷,堆管理器都會(huì)掃描空閑列表咬最,查找足夠大的第一個(gè)可用塊以授予請(qǐng)求。
- GetProcessHeap
如果您滿足于使用當(dāng)前程序擁有的默認(rèn)堆欠动,則GetProcessHeap就足夠了永乌。
GetProcessHeap PROTO
示例:
.data
hHeap HANDLE ?
.code
INVOKE GetProcessHeap
.IF eax == NULL ; cannot get handle
jmp quit
.ELSE
mov hHeap,eax ; handle is OK
.ENDIF
- HeapCreate
創(chuàng)建私有堆空間
HeapCreate PROTO,
flOptions:DWORD, ; heap allocation options
dwInitialSize:DWORD, ; initial heap size, in bytes
dwMaximumSize:DWORD ; maximum heap size, in bytes
flOptions
設(shè)置為NULL
dwInitialSize
設(shè)置為初始堆大小(以字節(jié)為單位)具伍。 該值向上舍入到下一頁邊界
HeapAlloc
調(diào)用時(shí)超過初始堆大小時(shí)翅雏,它將增大到您在dwMaximumSize參數(shù)中指定的值(向上舍入到下一頁邊界)。 調(diào)用它之后人芽,EAX中的空返回值表示未創(chuàng)建堆
示例:
HEAP_START = 2000000 ; 2 MB
HEAP_MAX = 400000000 ; 400 MB
.data
hHeap HANDLE ? ; handle to heap
.code
INVOKE HeapCreate, 0, HEAP_START, HEAP_MAX
.IF eax == NULL ; heap not created
call WriteWindowsMsg ; show error message
jmp quit
.ELSE
mov hHeap,eax ; handle is OK
.ENDIF
- HeapDestroy
HeapDestroy 函數(shù)銷毀已存在的私有堆空間
HeapDestroy PROTO,
hHeap:DWORD ; heap handle
示例:
.data
hHeap HANDLE ? ; handle to heap
.code
INVOKE HeapDestroy, hHeap
.IF eax == NULL
call WriteWindowsMsg ; show error message
.ENDIF
- HeapAlloc
HeapAlloc 函數(shù)在已存在的堆中申請(qǐng)內(nèi)存塊
HeapAlloc PROTO,
hHeap:HANDLE, ; handle to existing heap block
dwFlags:DWORD, ; heap allocation control flags
dwBytes:DWORD ; number of bytes to allocate
hHeap
一個(gè)由GetProcessHeap或HeapCreate初始化的堆的32位句柄望几。
dwFlags
包含一個(gè)或多個(gè)標(biāo)志值的雙字。 您可以選擇將其設(shè)置為HEAP_ZERO_MEMORY萤厅,它將內(nèi)存塊設(shè)置為全零橄抹。
dwBytes
靴迫,一個(gè)雙字,表示堆分配的大小楼誓,以字節(jié)為單位
.data
hHeap HANDLE ? ; heap handle
pArray DWORD ? ; pointer to array
.code
INVOKE HeapAlloc, hHeap, HEAP_ZERO_MEMORY, 1000
.IF eax == NULL
mWrite "HeapAlloc failed"
jmp quit
.ELSE
mov pArray,eax
.ENDIF
- HeapFree
HeapFree 函數(shù)在已經(jīng)存在的內(nèi)存塊中釋放私有空間矢劲。
HeapFree PROTO,
hHeap:HANDLE,
dwFlags:DWORD,
lpMem:DWORD
示例:
INVOKE HeapFree, hHeap, 0, pArray
- Error Handling
如果在調(diào)用HeapCreate,HeapDestroy或GetProcessHeap時(shí)遇到錯(cuò)誤慌随,可以通過調(diào)用GetLastError API函數(shù)來獲取詳細(xì)信息。
INVOKE HeapCreate, 0,HEAP_START, HEAP_MAX
.IF eax == NULL ; failed?
call WriteWindowsMsg ; show error message
.ELSE
mov hHeap,eax ; success
.ENDIF
1). 堆測(cè)試程序
; 堆測(cè)試
; 程序動(dòng)態(tài)申請(qǐng)1000個(gè)字節(jié)的內(nèi)存
INCLUDE Irvine32.inc
.data
ARRAY_SIZE = 1000
FILL_VAL EQU 0FFh
hHeap HANDLE ? ; 進(jìn)程堆句柄
pArray DWORD ? ; 指向內(nèi)存塊
newHeap DWORD ? ; 新堆的句柄
str1 BYTE "Heap size is: ",0
.code
main PROC
INVOKE GetProcessHeap ; 獲取堆句柄
.IF eax == NULL ; 如果獲取失敗躺同,則顯示異常信息
call WriteWindowsMsg
jmp quit
.ELSE
mov hHeap,eax ; 獲取成功
.ENDIF
call allocate_array
jnc arrayOk ; 失敗阁猜,設(shè)置CF=1
call WriteWindowsMsg
call Crlf
jmp quit
arrayOk: ; 字節(jié)填充
call fill_array
call display_array
call Crlf
; free the array
INVOKE HeapFree, hHeap, 0, pArray
quit:
exit
main ENDP
;--------------------------------------------------------
allocate_array PROC USES eax
; 為數(shù)組動(dòng)態(tài)申請(qǐng)內(nèi)存空間
; Receives: EAX = handle to the program heap
; Returns: CF = 0 if the memory allocation succeeds.
;--------------------------------------------------------
INVOKE HeapAlloc, hHeap, HEAP_ZERO_MEMORY, ARRAY_SIZE
.IF eax == NULL
stc ; 返回時(shí)CF=1
.ELSE
mov pArray,eax ; 保存指針
clc ; 返回時(shí)CF=0
.ENDIF
ret
allocate_array ENDP
;--------------------------------------------------------
fill_array PROC USES ecx edx esi
; 填充單個(gè)字符
; Receives: nothing
; Returns: nothing
;--------------------------------------------------------
mov ecx,ARRAY_SIZE ; 循環(huán)計(jì)數(shù)
mov esi,pArray ; 數(shù)組指針
L1: mov BYTE PTR [esi],FILL_VAL ; 填充每個(gè)字節(jié)
inc esi ; 下一個(gè)位置
loop L1
ret
fill_array ENDP
;--------------------------------------------------------
display_array PROC USES eax ebx ecx esi
; 顯示數(shù)組
; Receives: nothing
; Returns: nothing
;--------------------------------------------------------
mov ecx,ARRAY_SIZE ; 循環(huán)計(jì)數(shù)
mov esi,pArray ; 數(shù)組指針
L1: mov al,[esi] ; 獲取一個(gè)字節(jié)
mov ebx,TYPE BYTE
call WriteHexB ; 顯示
inc esi ; 下一個(gè)位置
loop L1
ret
display_array ENDP
END main
4. x86 內(nèi)存管理
- 將邏輯地址轉(zhuǎn)換為線性地址
- 將線性地址轉(zhuǎn)換為物理地址(分頁)
1). 線性地址
- 將邏輯地址轉(zhuǎn)換為線性地址
多任務(wù)操作系統(tǒng)允許多個(gè)程序(任務(wù))同時(shí)在內(nèi)存中運(yùn)行。 每個(gè)程序都有自己獨(dú)特的數(shù)據(jù)區(qū)域蹋艺。 假設(shè)三個(gè)程序每個(gè)都有一個(gè)偏移量為200h的變量; 三個(gè)變量如何在不共享的情況下彼此分離剃袍? 答案是x86處理器使用一步或兩步過程將每個(gè)變量的偏移量轉(zhuǎn)換為唯一的內(nèi)存位置.
第一步將段值與變量的偏移量組合在一起以創(chuàng)建線性地址。 該線性地址可以是變量的物理地址捎谨。 但是民效,諸如MS-Windows和Linux之類的操作系統(tǒng)采用稱為分頁的功能,以允許程序使用比計(jì)算機(jī)中物理可用的線性內(nèi)存更多的線性內(nèi)存涛救。 他們必須使用稱為頁面轉(zhuǎn)換的第二步將線性地址轉(zhuǎn)換為物理地址畏邢。
分頁
分頁是x86處理器的一個(gè)重要特性,它使計(jì)算機(jī)可以運(yùn)行一些本來不適合內(nèi)存的程序組合检吆。 處理器通過最初僅將部分程序加載到內(nèi)存中舒萎,同時(shí)將剩余部分保留在磁盤上來完成此操作。 程序使用的內(nèi)存分為稱為頁面的小單元蹭沛,每個(gè)單元通常為4 KB臂寝。 當(dāng)每個(gè)程序運(yùn)行時(shí),處理器選擇性地從內(nèi)存中卸載非活動(dòng)頁面并加載其他立即需要的頁面摊灭。描述表
段描述符可以在兩種類型的表中找到:全局描述符表和本地描述符表咆贬。
全局描述符表——當(dāng)操作系統(tǒng)在啟動(dòng)期間將處理器切換到保護(hù)模式時(shí),會(huì)創(chuàng)建單個(gè)GDT掏缎。 其基址保存在GDTR(全局描述符表寄存器)中。
本地描述符表——在多任務(wù)操作系統(tǒng)中萝挤,通常為每個(gè)任務(wù)或程序分配其自己的段描述符表御毅,稱為L(zhǎng)DT。 LDTR寄存器包含程序LDT的地址怜珍。段描述符詳細(xì)信息
除了段的基址之外端蛆,段描述符還包含指定段限制和段類型的位映射字段。
2). 頁面翻譯
啟用分頁時(shí)酥泛,處理器必須將32位線性地址轉(zhuǎn)換為32位物理地址今豆。 該過程中使用了三種結(jié)構(gòu):
?頁面目錄:最多1024個(gè)32位頁面目錄條目的數(shù)組嫌拣。
?頁表:最多1024個(gè)32位頁表?xiàng)l目的數(shù)組。
?頁面:4 KB或4 MB的地址空間呆躲。