汇编语言实例:动态内存分配


下面的示例程序使用动态内存分配创建并填充了一个 1000 字节的数组:
; 堆测试 #1        (Heaptest1.asm)

INCLUDE Irvine32.inc
; 使用动态内存分配,本程序分配并填充一个字节数据
.data
ARRAY_SIZE = 1000
FILL_VAL EQU 0FFh

hHeap   DWORD ?        ; 程序堆句柄
pArray  DWORD ?        ; 内存块指针
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                  ; 失败 (CF = 1)?
    call    WriteWindowsMsg
    call    Crlf
    jmp    quit

arrayOk:                            ; 成功填充数组
    call    fill_array
    call    display_array
    call    Crlf

    ; 释放数组
    INVOKE HeapFree, hHeap, 0, pArray
   
quit:
    exit
main ENDP

;--------------------------------------------------------
allocate_array PROC USES eax
;
; 动态分配数组空间
; 接收: EAX = 程序堆句柄
; 返回: 如果内存分配成功,则 CF = 0
;--------------------------------------------------------
    INVOKE HeapAlloc, hHeap, HEAP_ZERO_MEMORY, ARRAY_SIZE
   
    .IF eax == NULL
       stc                    ; 返回 CF = 1
    .ELSE
       mov  pArray,eax        ; 保存指针
       clc                    ; 返回 CF = 0
    .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      (Heaptest2.asm)

INCLUDE Irvine32.inc
.data
HEAP_START =   2000000    ;   2 MB
HEAP_MAX  =  400000000    ; 400 MB
BLOCK_SIZE =    500000    ;  0.5 MB

hHeap DWORD ?             ; 堆句柄
pData DWORD ?             ; 块指针

str1 BYTE 0dh,0ah,"Memory allocation failed",0dh,0ah,0

.code
main PROC
    INVOKE HeapCreate, 0,HEAP_START, HEAP_MAX

    .IF eax == NULL          ; 失败?
    call    WriteWindowsMsg
    call    Crlf
    jmp    quit
    .ELSE
    mov    hHeap,eax          ; 成功
    .ENDIF

    mov    ecx,2000           ; 循环计数器

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             ; 保存指针
       clc                        ; 返回 CF = 0
    .ENDIF

    ret
allocate_block ENDP

free_block PROC USES ecx

    INVOKE HeapFree, hHeap, 0, pData
    ret
free_block ENDP

END main