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

Assembly 填充动态分配的内存会冻结程序的执行,assembly,dos,x86-16,tasm,Assembly,Dos,X86 16,Tasm,使用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

使用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
由于执行后未设置进位标志,因此它的工作似乎完美无缺 说明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      
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
[编辑]

使用上述代码,程序内存的高端最终看起来如下所示:

    .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 -->
.DATA。堆栈函数48h alloc
...  ...
94h,08h,0,0,…,0
^               ^                ^

0883h 0884h 0894h很抱歉回到这里,但我需要一些澄清罗兰。Dos 48h为我分配了一些内存(如果有的话),并在case中返回一个段落地址。现在我认为“段落”只是“片段”的另一个词,不是吗?但是,如果我做一些类似于MOV-ES、buffer-MOV-AX、SEG-buffer(获取段地址)的事情,并最终比较AX和ES中的值,我会得到ES中的894h和AX中的段地址中的883h。造成差异的原因是什么?缓冲区是BSS中变量的名称(
.DATA?
)。在这里,该变量位于某个“偏移”处,BSS本身也位于某个“SEG”处。汇编程序允许您通过
mov ax,offset buffer
mov ax,seg buffer
检索这些值。
mov es,buffer
指令的作用是检索存储在变量中的值。所以和变量在内存中的位置无关。是的,我完全知道这些指令和我自己的变量的作用-我不知道的是片段和段落之间的区别。根据我的想法,在int 21h之后返回到AX寄存器的段落地址是段地址。显然不是因为这两个值相差17字节。那这两个是什么重读我的解释。这两个值必须不同(可能性很大)。它们是完全不同的东西。为什么它们必须保持相同的值?段地址和段落地址本质上是一样的。每个段(64KB)从内存中的段落地址开始。每个段落都是一个16字节的内存块。1MB内存中有65536个严重重叠的64KB段。
.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 -->