I can't figured out how to allocate 64 000 bytes of memory.
i CANT also use an array like this: myarrray byte 64000 dup (0) because the segment restriction of 64kb
I tried this code but i cant to allocate more than 64 pages of memory ( 1 page = 16 bytes )
mov ah, 48h
mov bx, 640000/16
int 21h
jnc @F
; Cant not allocate memory
exit
I want to allocate memory because I am doing 16 bits Graphics programming and i need to allocate memory for a buffer of 64 000 bytes for flipping graphics into the screen
I really appreciate any help.
a segment can hold 65,536 bytes
or, i should say, you can address 65,536 bytes with a single segment value
although, with older assemblers, it didn't like that last byte - lol
you could put 65,535 in there and fake the last one
anyways, it will hold 64,000 bytes
as for allocating the memory, if it is an EXE, you already own all available memory
use the forum search tool - we had a discussion about this very recently
here you go...
http://www.masm32.com/board/index.php?topic=16383.0
One question if I use the function 4AH and int 21h to resize the memory at the begenning of the progran to 32000 which is half of the maximim memory that a 16 bit program can have.
Is that TRICK fine? or it will cause the program to act wierd later on?
Man, I just need 64k of memory for my flipping buffer.
This is my code I use the Irvine 16 library:
INCLUDE Irvine16.inc
.data
coord struct
y word 0
x word 0
coord ends
.code
main PROC
mov ax,@data
mov ds,ax
clc
; resize the memory to about half of the max
mov ah, 4ah
MOV BX, 32000
INT 21H
jnc NEXT
mov eax, 66
call WriteDec
call WaitMsg
NEXT:
clc
mov ah, 48h
MOV BX, 4000 ; allocate 64000 bytes
INT 21H
jnc NEXT2
movzx eax, bx
call WriteDec
call WaitMsg
NEXT2:
exit
main ENDP
END main
:bg
as i said, you already own the memory
you can check the BIOS data area to see how much total memory is available
then, use a label at the end of your last data segment to get the address of the end of your program
create a segment at the next paragraph (16 byte boundry)
(actually, you don't "create" anything, you merely calculate the segment base and store/use it)
verify there is enough space by checking the word at 0040:0013
http://www.o3one.org/hwdocs/bios_doc/BIOS_SEG.txt
i don't know how many or what type of segments you are using
if you have a bss segment, that is probably the last
you can check it by creating a MAP file with LINK or EXEMAP
This example should work for any normal .EXE (but probably not for a .COM file).
;=========================================================================
.model small
.386
.stack
;=========================================================================
.data
junk dd 16 dup(0)
.code
;=========================================================================
start:
;=========================================================================
; .startup ; this for compatibility test
;---------------------------------------------------------------
; For the 16-bit memory models the program loader leaves DS and
; ES set to the segment address of the Program Segment Prefix
; (PSP) that precedes the program in memory. To access the
; program (near) data DS must be set to the segment address of
; the data segment.
;---------------------------------------------------------------
mov ax, @data
mov ds, ax
;-----------------------------------------------------------------
; This code shrinks the program memory allocation to the minimum
; required by the program code, data, and stack.
;
; The code segment is at the start of the program (immediately
; following the PSP), the stack segment is at end of the program,
; and the program loader sets SP to the end of the stack. So to
; calculate the new size, in paragraphs, this code subtracts the
; segment address of the code segment from the segment address of
; the stack segment and adds the size of the stack in paragraphs.
;
; And note that the Set Memory Block Size function expects ES to
; contain the segment address of the memory block to resize,
; which in this case *must* be the segment address of the PSP.
;-----------------------------------------------------------------
mov ax, cs
mov bx, ss
sub bx, ax
mov dx, sp
shr dx, 4 ; convert to paragraphs
inc dx ; adjust for any bits lost in shift
add bx, dx
mov ah,4Ah ; Set Memory Block Size
int 21h
xor ah, ah
int 16h
.exit
;=========================================================================
end start
Hi,
You can create an "extra" segment to hold your buffer. By
naming a segment to something other that CODE, STACK, and
the like, you can allocate the entire segment to your buffer. I
use that 'trick' when I need more than 65,000 bytes of data for
a program. I generally do not use the simplified directives, so
I use the older segment definitions. An example follows. Perhaps
someone familiar with the simplified directives knows a better way.
This is not a complete example. It is simplified a bit.
Regards,
Steve N.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants. Data segment:
DATASG SEGMENT PUBLIC
ASSUME DS:DATASG, SS:STCKSG, CS:CODE
; This is tha old fashioned way to specify the .DATA directive
; stuff. Shown only to explain what would happen if you use only
; the older directives.
DATASG ENDS
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants. Data segment:
EXTRASG SEGMENT PUBLIC
ASSUME ES:EXTRASG
; Define your buffer here.
BUFFER DB 65000 DUP( 0 )
EXTRASG ENDS
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants. Code segment:
CODE SEGMENT PUBLIC ; Again this would be .CODE in your program!
START PROC FAR
ASSUME CS:CODE,DS:DATASG,ES:NOTHING,SS:STCKSG
MOV AX,SEG DATASG ; Set DS for rest of code ...
MOV DS,AX
; When you need to access the extra segment you will do something like...
PUSH ES
MOV AX,SEG EXTRASG
MOV ES,AX
ASSUME ES:EXTRASG
; You do what you want to.
MOV AX,WORD PTR ES:[BUFFER]
; Then clean up. Or whatever.
POP ES
ASSUME ES:NOTHING
; And exit.
START ENDP
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CODE ENDS
END START
Edit: DW => DB size fix.
SRN
BUFFER DB 65000 DUP( 0 )
i would use
BUFFER DB 64000 DUP(?)
if you fill it with 0, it will increase the size of the EXE file
if you use uninitialized data, it shouldn't
With the simplified segment directives you can use .FARDATA or .FARDATA?