▶ 书中第十一章的程序,主要讲了 Windows 接口,在小黑框中进行程序交互
● 在屏幕指定位置输出带自定义属性的文字
INCLUDE Irvine32.inc .data
outHandle HANDLE ?
cellsWritten DWORD ? ; 输出计数(输出参数)
xyPos COORD <,> ; 输出坐标
buffer BYTE 41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,50h,51h,52h,53h,54h
BufSize DWORD ($ - buffer)
attributes WORD 1h,2h,3h,4h,5h,6h,7h,8h,9h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,10h,,12h,13h,14h .code
main PROC
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov outHandle, eax
INVOKE WriteConsoleOutputAttribute, outHandle, ADDR attributes, BufSize, xyPos, ADDR cellsWritten ; 设置输出属性
INVOKE WriteConsoleOutputCharacter, outHandle, ADDR buffer, BufSize, xyPos, ADDR cellsWritten ; 输出 call ReadChar
;call WaitMsg ; 与 ReadChar 等效
exit
main ENDP
END main
● 动态内存分配 1
INCLUDE Irvine32.inc .data
ARRAY_SIZE = ; 要申请的数组尺寸
FILL_VAL EQU 0FFh ; 数组填充的值 hHeap DWORD ?
pArray DWORD ? ; 堆内存指针
str1 BYTE "Heap size is: ", .code
main PROC
INVOKE GetProcessHeap ; 获取堆内存的指针
.IF eax == NULL
call WriteWindowsMsg
jmp quit
.ELSE
mov hHeap, eax
.ENDIF call allocate_array
jnc arrayOk ; 申请成功 CF = 0,失败 CF = 1
call WriteWindowsMsg
call Crlf
jmp quit arrayOk: ; 填充和输出数组
call fill_array
call display_array
call Crlf INVOKE HeapFree, hHeap, , pArray ; 释放申请的内存 quit:
call WaitMsg
exit
main ENDP allocate_array PROC USES eax ; 申请堆内存
INVOKE HeapAlloc, hHeap, HEAP_ZERO_MEMORY, ARRAY_SIZE .IF eax == NULL
stc ; 申请失败,置 CF = 1
.ELSE
mov pArray,eax ; 申请成功,保存内存指针,置 CF = 0
clc
.ENDIF ret
allocate_array ENDP fill_array PROC USES ecx edx esi
mov ecx, ARRAY_SIZE
mov esi, pArray L1:
mov BYTE PTR [esi], FILL_VAL
inc esi
loop L1 ret
fill_array ENDP display_array PROC USES eax ebx ecx esi
mov ecx, ARRAY_SIZE
mov esi, pArray L1:
mov al, [esi]
mov ebx, TYPE BYTE
call WriteHexB
inc esi
loop L1 ret
display_array ENDP END main
● 动态内存分配 2,申请多个内存堆,直到溢出
INCLUDE Irvine32.inc .data
HEAP_START = ; 2 MB
HEAP_MAX = ; 400 MB
BLOCK_SIZE = ; .5 MB hHeap DWORD ?
pData DWORD ? str1 BYTE 0dh,0ah,"Memory allocation failed",0dh,0ah, .code
main PROC
INVOKE HeapCreate, ,HEAP_START, HEAP_MAX .IF eax == NULL ; 申请失败
call WriteWindowsMsg
call Crlf
jmp quit
.ELSE ; 申请成功
mov hHeap, eax
.ENDIF mov ecx, L1:
call allocate_block ; 申请内存堆
.IF Carry? ; 失败
mov edx,OFFSET str1
call WriteString
jmp quit
.ELSE ; 成功,
mov al,'.' ; 输出一个点
call WriteChar ; 显示进度
.ENDIF ;call free_block ; 是否把刚申请的堆释放掉
loop L1 quit:
INVOKE HeapDestroy, hHeap ; 释放掉所有的堆
.IF eax == NULL ; 失败则显示信息
call WriteWindowsMsg
call Crlf
.ENDIF exit
main ENDP allocate_block PROC USES ecx
INVOKE HeapAlloc, hHeap, HEAP_ZERO_MEMORY, BLOCK_SIZE .IF eax == NULL
stc ; 失败,置 CF = 1
.ELSE
mov pData,eax ; 成功,指针保存到 eax
clc ; 置 CF = 0
.ENDIF ret
allocate_block ENDP free_block PROC USES ecx
INVOKE HeapFree, hHeap, , pData
ret
free_block ENDP END main
● 文件读写(有点问题,尚未完成)
INCLUDE Irvine32.inc
INCLUDE macros.inc BUFFER_SIZE = .data
buffer BYTE "abcdef",
filename BYTE "output.txt",
fileHandle HANDLE ?
stringLength DWORD ?
bytesWritten DWORD ? .code
main PROC mov edx, OFFSET filename
call CreateOutputFile
mov fileHandle, eax
cmp eax, INVALID_HANDLE_VALUE ; 错误检查
jne file_ok1
mWrite <"Failed to create output file",0dh,0ah>
jmp quit file_ok1:
mov eax, fileHandle ; 写入文件
mov edx, OFFSET buffer
mov ecx, SIZEOF buffer
call WriteToFile
mov bytesWritten, eax ; 返回写入字符串长度
call CloseFile mWrite <"Bytes written to file [output.txt]: "> ; 显示写入字符串长度
mov eax, bytesWritten
call WriteDec
call Crlf
call WaitMsg mov eax, SIZEOF filename ; 打开文件
mov edx, OFFSET filename
call OpenInputFile
mov fileHandle, eax cmp eax, INVALID_HANDLE_VALUE ; 错误检查
jne file_ok2
mWrite <"Failed to open the file",0dh,0ah>
jmp quit file_ok2:
mov edx, OFFSET buffer ; 读取文件
mov ecx, BUFFER_SIZE
call ReadFromFile
jnc check_buffer_size
mWrite <"Failed to read the file.", 0dh, 0ah>
call WriteWindowsMsg
jmp close_file check_buffer_size: ; 检查是否超出缓冲区大小
cmp eax, BUFFER_SIZE
jb buf_size_ok
mWrite <"Failed to read the file into buffer", 0dh, 0ah>
jmp quit buf_size_ok:
mov buffer[eax], ; insert null terminator
mWrite "File size: "
call WriteDec ; display file size
call Crlf mWrite <"Buffer:",0dh,0ah,0dh,0ah>
mov edx,OFFSET buffer ; display the buffer
call WriteString
call Crlf close_file:
mov eax, fileHandle
call CloseFile quit:
call WaitMsg
exit
main ENDP
END main