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



使用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标志指令21 h。

之后,我最终试图填充刚刚分配的内存,如:

    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 buffer以0加载AX,因为缓冲区变量占用了BSS中的第一个单词。
mov ax, seg buffer用0883h加载AX, 0883h是程序加载时分配给BSS的段地址。
mov ax, buffer用0894h加载AX,这是缓冲区变量的内容,这是DOS分配给64000字节分配的段地址。

关于分段和段落的更多解释,请阅读:什么是分段以及如何在8086模式下对分段进行处理?

相关内容

  • 没有找到相关文章

最新更新