x86 程序集 MASM 中的动态堆内存

Dynamic Heap Memory in x86 Assembly MASM

我在 Kip Irvine 的 Assembly x86 一书中找到的以下示例使用动态内存分配重复分配大块内存,直到超过堆大小。我通过包含 WriteWindowsMsg 过程修改了部分代码,因为出于某些奇怪的原因,我收到一个错误消息,指出该过程不存在。这是修改后的代码:

; Heap Test #2 (Heaptest2.asm)
INCLUDE Irvine32.inc
.data

HANDLE TEXTEQU <DWORD>

HeapCreate PROTO,
flOptions:DWORD, ; heap allocation options
dwInitialSize:DWORD, ; initial heap size, in bytes
dwMaximumSize:DWORD ; maximum heap size, in bytes

LocalFree PROTO,
pErrorMsg:DWORD 




FormatMessage PROTO,
FORMAT_MESSAGE_ALLOCATE_BUFFER: DWORD,
messageID: DWORD, 
messageID: BYTE,
pErrorMsg: DWORD



HeapDestroy PROTO,
hHeap:DWORD ; heap handle


HeapAlloc PROTO,
hHeap:HANDLE, ; handle to existing heap block
HEAP_ZERO_MEMORY:DWORD, ; heap allocation control flags
BLOCK_SIZE:DWORD ; number of bytes to allocate


HeapFree PROTO,
hHeap:HANDLE,
dwFlags:DWORD,
lpMem:DWORD



HEAP_START = 2000000 ; 2 MByte

HEAP_MAX = 400000000 ; 400 MByte
BLOCK_SIZE = 500000 ; .5 MByte
hHeap HANDLE ? ; handle to the heap
pData DWORD ? ; pointer to block
str1 BYTE 0dh,0ah,"Memory allocation failed",0dh,0ah,0
HEAP_ZERO_MEMORY DWORD ?
WriteWindowsMsg_1 BYTE "Error ",0 
WriteWindowsMsg_2 BYTE ": ",0 
pErrorMsg DWORD ? 
messageId DWORD ? 


.code

main PROC

INVOKE HeapCreate, 0,HEAP_START, HEAP_MAX
.IF eax == NULL ; failed?
    call WriteWindowsMsg
    call Crlf
    jmp quit
.ELSE
    mov hHeap,eax ; success
.ENDIF
    mov ecx,2000 ; loop counter
    L1: call allocate_block ; allocate a block
.IF Carry? ; failed?
    mov edx,OFFSET str1 ; display message
    call WriteString
    jmp quit
.ELSE ; no: print a dot to
    mov al,'.' ; show progress
    call WriteChar
.ENDIF
;call free_block ; enable/disable this line
loop L1
quit:
    INVOKE HeapDestroy, hHeap ; destroy the heap
.IF eax == NULL ; failed?
    call WriteWindowsMsg ; yes: error message
    call Crlf
.ENDIF
exit
main ENDP


allocate_block PROC USES ecx
; allocate a block and fill with all zeros.
INVOKE HeapAlloc, hHeap, HEAP_ZERO_MEMORY, BLOCK_SIZE
.IF eax == NULL
    stc ; return with CF = 1
.ELSE
    mov pData,eax ; save the pointer
    clc ; return with CF = 0
.ENDIF
ret
allocate_block ENDP


free_block PROC USES ecx
INVOKE HeapFree, hHeap, 0, pData
ret
free_block ENDP




WriteWindowsMsg PROC USES eax edx 

call GetLastError 
mov messageId, eax 
mov edx, OFFSET WriteWindowsMsg_1 
call WriteString 
call WriteDec 
mov edx, OFFSET WriteWindowsMsg_2 
call WriteString 

INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \
    FORMAT_MESSAGE_FROM_SYSTEM, NULL, messageID, NULL, 
    ADDR pErrorMsg, NULL, NULL 

mov edx, pErrorMsg 
call WriteString 

INVOKE LocalFree, pErrorMsg 

ret 
WriteWindowsMsg ENDP



END main

我得到的结果如下:

 Assembling: bobnew.asm
bobnew.asm(122) : error A2136: too many arguments to INVOKE
bobnew.asm(122) : error A2114: INVOKE argument type mismatch : argument : 3
bobnew.asm(122) : error A2006: undefined symbol : FORMAT_MESSAGE_ALLOCATE_BUFFER

bobnew.asm(122) : error A2114: INVOKE argument type mismatch : argument : 1
bobnew.asm(114) : error A2006: undefined symbol : GetLastError
Press any key to continue . . .

谁能解释一下我的代码哪里做错了?谢谢

每个当前 irvine32.lib 包含 WriteWindowsMsg。您的安装出现问题。

Kip Irvine's homepage ("...link 库...") 获取 irvine32.incirvine32.lib 以及确保汇编程序使用 irvine32.inc 而 linker 使用 irvine32.lib.

看看Irvine's installation hints ("Getting started with MASM...").

我无法在我的系统上收到您的错误消息。 FORMAT_MESSAGE_ALLOCATE_BUFFERFormatMessage 的原型中用作参数名称,在 invoke 调用中用作常量。如果常量未在其他任何地方定义(例如在 -lib 文件中),则它是未知的。不知道为什么你的系统找不到GetLastError.