News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Reallocating memory with int 21h

Started by untio, May 12, 2013, 12:19:32 AM

Previous topic - Next topic

untio

Hi,

First of all, thanks for reading this stuff.

I am writing a msdos program that needs to assign memory dinamically. I know that previously I must reduce the memory assigned to my program. Then, i have written this macro that is just at the startup of the program:

;--------------------------------
;AJUSTA LA MEMORIA USADA POR EL
;PROGRAMA AL MINIMO NECESARIO.
;ES NECESARIO PARA PODER USAR
;MEMORIA DINAMICA YA QUE AL
;PRINCIPIO NO HAY MEMORIA LIBRE
;PORQUE EL SISTEMA LA ASIGNA TODA
;AL PROGRAMA.
__AJUSMEM MACRO
        MOV     BX, SS
        MOV     AX, ES
        SUB     BX, AX
        MOV     AX, SP
        SHR     AX, 4
        ADD     AX, 2 <------
        ADD     BX, AX
        MOV     AH, 4AH
        INT     21H
ENDM    __AJUSMEM
;--------------------------------


My doubt is that (in the line with the arrow) I have seen in all the internet examples simply an INC AX, but if I use only inc the program seems to work but when finishes msdos hangs.

My question is if this method is correct or I shall need in some future add 3, 4 or another number to AX. Or I am wrong.

Thanks in advance.

Gunther

Hi untio

here is one procedure (TASM syntax) which will resize your DOS memory during runtime for later new allocation. You should call it in an early program stage:

;ResMem
;Task:             Resize the program's memory block for later allocation.
;Input:            None
;Output:           cf = 0 ===> success, memory block resized
;                  cf = 1 ===> failure
;Uses:             DOS Interrupt 21h
ResMem  proc       near
push       ax
push       bx
mov        ax, sp               ; ss:sp -> end of program
shr        ax, 4
mov        bx, ss
add        bx, ax
inc        bx                   ; bx = first paragraph beyond program
mov        ax, es               ; es:0000 -> first program paragraph
sub        bx, ax               ; bx = program size in paragraphs
mov        ah, 4ah              ; FUNCTION: resize memory block
int        21h                  ; transfer to DOS
@@10:   
        pop        bx
pop        ax
ret
ResMem  endp


I hope that helps a bit.

Gunther
You have to know the facts before you can distort them.

untio

Hi,

First, thanks for your answer. But it doesn't work with my program. I adjoint my full code to this post.

Thanks once more.




MichaelW

Assembling with ML 6.15 using ml /W3 /c:

DRIVES.ASM:
DRIVES.ASM(16) : error A2179: structure improperly initialized
DRIVES.ASM(16) : error A2008: syntax error : in structure
DRIVES.ASM(34) : error A2006: undefined symbol : MARCODRIVES
Fix was to change:
MARCODRIVES MARCO ?
To:
MARCODRIVES MARCO <>

PANTALLA.ASM: No warnings, no errors
MILIB.ASM: No warnings, no errors
MAIN.ASM: No warnings, no errors

Linking with Link16 from the MASM32 distribution using:

\masm32\bin\link16 /INFORMATION /MAP MAIN.OBJ MILIB.OBJ DRIVES.OBJ PANTALLA.OBJ;


C:\MASMDOS\untio>\masm32\bin\link16 /INFORMATION /MAP MAIN.OBJ MILIB.OBJ DRIVES.
OBJ PANTALLA.OBJ;

Microsoft (R) Segmented Executable Linker  Version 5.60.339 Dec  5 1994
Copyright (C) Microsoft Corp 1984-1993.  All rights reserved.

**** PARSING DEFINITIONS FILE ****
**** PASS ONE ****
MAIN.OBJ(MAIN.ASM)
MILIB.OBJ(MILIB.ASM)
DRIVES.OBJ(DRIVES.ASM)
PANTALLA.OBJ(PANTALLA.ASM)
**** SEARCHING LIBRARIES ****
**** ASSIGNING ADDRESSES ****
  1 segment "_TEXT" class "CODE" length 2b6H bytes
  2 segment "_DATA" class "DATA" length 0H bytes
  3 segment "STACK" class "STACK" length 800H bytes
  4 segment "_BSS" class "BSS" length 15H bytes
  5 segment "CONST" class "CONST" length 18H bytes
**** PRINTING MAP FILE ****
**** PASS TWO ****
MAIN.OBJ(MAIN.ASM)
MILIB.OBJ(MILIB.ASM)
DRIVES.OBJ(DRIVES.ASM)
PANTALLA.OBJ(PANTALLA.ASM)
**** WRITING DOS EXECUTABLE ****


And here is the MAP file:

Start  Stop   Length Name                   Class
00000H 002B5H 002B6H _TEXT                  CODE
002B6H 002B6H 00000H _DATA                  DATA
002C0H 00ABFH 00800H STACK                  STACK
00AC0H 00AD4H 00015H _BSS                   BSS
00AD6H 00AEDH 00018H CONST                  CONST

Origin   Group
002B:0   DGROUP

  Address         Publics by Name

0000:026A       DIBUJARFONDO
0000:0216       DIBUJARMARCO
0000:02A9       DIBUJARPANTALLA
0000:01FA       DIBUJARPLANOMARCO
0000:028F       DIBUJARTITULO
0000:01DA       DIBUJARVERTICALMARCO
0000:0134       INICIARDRIVES
0000:00EB       PRINTENMEDIO
0000:0088       PRINTSTR
0000:0060       SETMEM
0000:0058       ZEROMEMORY

  Address         Publics by Value

0000:0058       ZEROMEMORY
0000:0060       SETMEM
0000:0088       PRINTSTR
0000:00EB       PRINTENMEDIO
0000:0134       INICIARDRIVES
0000:01DA       DIBUJARVERTICALMARCO
0000:01FA       DIBUJARPLANOMARCO
0000:0216       DIBUJARMARCO
0000:026A       DIBUJARFONDO
0000:028F       DIBUJARTITULO
0000:02A9       DIBUJARPANTALLA

Program entry point at 0000:0000

Segments   5
Groups       1
Bytes in symbol table  1921


As you can see the stack is not at the end of the program, although for your purposes I think you can discard the BSS and CONST segments without problems.

When you convert the calculated size in bytes to a size in paragraphs with a SHR 4, you are shifting 4 bits out of the value. If these 4 bits were 0000b then no problem, otherwise your calculated size in paragraphs is one paragraph too small. The normal way of correcting for this is to add one paragraph, and this is the reason for the INC AX you have seen.
Well Microsoft, here's another nice mess you've gotten us into.

untio

Hi,

First of all, thanks to MichaelW for his answer and for give me the clue.

The problem was with the bss segment. It was after the stack. I have changed this:

.STACK 2048

.DATA?
  MODOVIDEO DB ?
  PAGINAVIDEO DB ?


Into:

.DATA?
  MODOVIDEO DB ?
  PAGINAVIDEO DB ?

.STACK 2048


And I have changed my macro to:

;--------------------------------
;AJUSTA LA MEMORIA USADA POR EL
;PROGRAMA AL MINIMO NECESARIO.
;ES NECESARIO PARA PODER USAR
;MEMORIA DINAMICA YA QUE AL
;PRINCIPIO NO HAY MEMORIA LIBRE
;PORQUE EL SISTEMA LA ASIGNA TODA
;AL PROGRAMA.
__AJUSMEM MACRO
        MOV     BX, SS
        MOV     AX, ES
        SUB     BX, AX
        MOV     AX, SP
        SHR     AX, 4
        INC     AX
        ADD     BX, AX
        MOV     AH, 4AH
        INT     21H
ENDM    __AJUSMEM
;--------------------------------


And now it runs right.

The problem was in that bss segment was after than the stack segment.

Once more, thanks a lot.

Cheers.

dedndave

you can use the .DOSSEG directive to control the order of segments
Start  Stop   Length Name                   Class
00000H 00020H 00021H _TEXT                  CODE
00022H 0002FH 0000EH _DATA                  DATA
00030H 00031H 00002H _BSS                   BSS
00040H 0083FH 00800H STACK                  STACK

        .MODEL  Small
        .STACK  2048
        .DOSSEG
        .386
        OPTION  CaseMap:None

;####################################################################################

        .DATA

s$Msg   db 'Hello World !',24h

;************************************************************************************

        .DATA?

label2  dw ?

;####################################################################################

        .CODE

;************************************************************************************

_main   PROC    FAR

        mov     ax,@data
        mov     ds,ax

        mov     dx,offset s$Msg
        mov     ah,9
        int     21h

        mov     ax,4C00h
        int     21h

_main   ENDP

;####################################################################################

        END     _main

untio

Hi,

Thanks to dedndave. I think that is better to use DOSSEG and put the directive of the stack at the beginning.

Only a comment: in my version of tasm DOSSEG is without the dot.

Thanks and cheers.

dedndave

the masm manual says it has a period
but, it seems to build either way