Using TASM I'm trying to allocate some memory which should serve as a buffer.
To do this I first deallocate all the memory which has been given to the executable using:
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
Afterwards I'm trying to allocate 64000 bytes using:
MOV AH, 48h
MOV BX, 64000/16
INT 21h
MOV buffer, AX
which seems to work flawlessly as the CARRY flag ain't set after executing instruction 21h.
Later on I'm ultimately trying to fill the just allocated memory like:
MOV BX, OFFSET BUFFER
MOV ES, BX
XOR DI,DI
MOV CX,64000/2
MOV AL,12
MOV AH,AL
REP STOSW
which unfortunately fails as the program freezes at the REP STOSW
instruction.
Now I'm a little lost as I can't find something obviously wrong. So why is this happening?
Here's my full source:
.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
The info that DOS function 48h gave you is a paragraph address.
The above code loads the offset to the variable that contains this address. You need to dereference it:
MOV ES, buffer
Directly from 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
[edit]
.MODEL LARGE .STACK 100h .DATA? buffer DW ? .CODE
With the above code, the high end of your program memory finally looks like:
.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 is the name of the first (and only) variable in your BSS (.DATA?
).
mov ax, offset buffer
loads AX
with 0 because the buffer variable occupies the very first word in the BSS.
mov ax, seg buffer
loads AX
with 0883h, the paragraph address of the BSS as assigned at program load time.
mov ax, buffer
loads AX
with 0894h, the contents of the buffer variable and that is the paragraph address that DOS assigned to the 64000-byte allocation.
For some more explanation about segments and paragraphs read this: What are Segments and how can they be addressed in 8086 mode?.