填充动态分配的内存会冻结程序执行

Filling dynamically allocated memory freezes program execution

我正在使用 TASM 尝试分配一些应该用作缓冲区的内存。

为此,我首先解除分配给可执行文件的所有内存:

    MOV     BX, SS 
    MOV     AX, ES  
    SUB     BX, AX  
    MOV     AX, SP 
    ADD     AX, 0fh
    SHR     AX, 4
    ADD     BX, AX
    MOV     AH, 4ah
    INT     21h

之后我尝试使用以下方式分配 64000 字节:

    MOV     AH, 48h
    MOV     BX, 64000/16 
    INT     21h
    MOV     buffer, AX

这似乎完美无缺,因为执行后未设置 CARRY 标志 指令 21h.

稍后我最终会尝试填充刚刚分配的内存,例如:

    MOV     BX, OFFSET BUFFER
    MOV     ES, BX

    XOR     DI,DI
   
    MOV     CX,64000/2
    MOV     AL,12
    MOV     AH,AL
    REP     STOSW

不幸的是失败了,因为程序在 REP STOSW 指令处冻结。 现在我有点迷路了,因为我找不到明显错误的东西。那么为什么会这样呢?

这是我的完整来源:

.MODEL LARGE

.STACK 100h
.DATA? 
buffer      DW ?

.CODE
Main:
    MOV     BX, SS 
    MOV     AX, ES  
    SUB     BX, AX  
    MOV     AX, SP 
    ADD     AX, 0fh
    SHR     AX, 4
    ADD     BX, AX
    MOV     AH, 4ah
    INT     21h

    MOV     AH, 48h
    MOV     BX, 64000/16 
    INT     21h
    MOV     buffer, AX

    MOV     BX, OFFSET BUFFER
    MOV     ES, BX

    XOR     DI,DI
   
    MOV     CX,64000/2
    MOV     AL,12
    MOV     AH,AL
    REP     STOSW

    MOV     AH,4ch  
    INT     21h 
   
END Main      
MOV     BX, OFFSET BUFFER
MOV     ES, BX

DOS函数48h给你的信息是一个段落地址。

以上代码将偏移量加载到包含该地址的变量。您需要取消引用它:

MOV     ES, buffer

直接来自 AX:

MOV     AH, 48h
MOV     BX, 64000/16 
INT     21h          ; -> AX CF

JC      Fail         ; Never forget to check for failure

MOV     buffer, AX
MOV     ES, AX
XOR     DI, DI
MOV     CX, 64000/2
MOV     AX, 0C0Ch
CLD                  ; Clear direction flag at least once in your program
REP     STOSW

Fail:
MOV     AX, 4C00h  
INT     21h

[编辑]

.MODEL LARGE

.STACK 100h
.DATA? 
buffer      DW ?

.CODE

通过上面的代码,你的程序内存的高端最终看起来像:

    .DATA?          .STACK           func 48h alloc
... <-- 16 bytes --><-- 256 bytes --><-- 64000 bytes --> ...
    94h,08h,0,0,..,0
    ^               ^                ^
    0883h           0884h            0894h    <== paragraph addresses
    <-- 272 bytes = 17 paragraphs -->

buffer 是 BSS (.DATA?) 中第一个(也是唯一一个)变量的名称。

mov ax, offset bufferAX 加载为 0,因为 buffer 变量占据了 BSS 中的第一个单词。
mov ax, seg buffer 加载 AX 0883h,即程序加载时分配的 BSS 段落地址。
mov ax, buffer 用 0894h 加载 AXbuffer 变量的内容,这是 DOS 分配给 64000 字节分配的段落地址。

有关段和段落的更多解释,请阅读: