2

The following example I have found in Kip Irvine's Assembly x86 book uses dynamic memory allocation to repeatedly allocate large blocks of memory until the heap size is exceeded. I have modified some parts of the code by including the WriteWindowsMsg procedure because for some odd reason, I am receiving an error that this procedure does not exist. Here is the modified code:

; 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

The following result I am getting is:

 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 . . .

Can someone explain what I am doing wrong on my code? Thanks

rkhb
  • 14,159
  • 7
  • 32
  • 60
jack black
  • 195
  • 1
  • 2
  • 11
  • 1) You added the wrong tag. This is apparently not related to C. 2) We are not a debugging service. Read [ask]. – too honest for this site Apr 22 '17 at 21:44
  • 1
    Did you actually read the error messages? You can usually trust them to tell you exactly what is wrong. And you seem to be confusing argument names and constants, like `FORMAT_MESSAGE_ALLOCATE_BUFFER`. – Rudy Velthuis Apr 22 '17 at 22:07

1 Answers1

1

Every current irvine32.lib contains WriteWindowsMsg. Something went wrong with your installation.

Get irvine32.inc and irvine32.lib from Kip Irvine's homepage ("...link library...") and make sure the assembler uses that irvine32.inc and the linker uses that irvine32.lib.

Take a look at Irvine's installation hints ("Getting started with MASM...").

I can't get your error messages on my system. FORMAT_MESSAGE_ALLOCATE_BUFFER is used in your prototype of FormatMessage as a name for a parameter and in the invoke call as a constant. If the constant is not defined anywhere else (e.g in a -lib file) it is unknown. I don't know why your system cannot find GetLastError.

rkhb
  • 14,159
  • 7
  • 32
  • 60