Assembly 填充动态分配的内存会冻结程序的执行
使用TASM,我试图分配一些应该用作缓冲区的内存 为此,我首先使用以下方法释放已分配给可执行文件的所有内存: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
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 -->