News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Novice questions on dynamic memory

Started by JRevor, March 06, 2010, 11:47:02 PM

Previous topic - Next topic

JRevor

Hello there!

I'm new to the community. I'm a computer engineering III student (systems). I've already programmed on C++, Pascal, and some other languages for university projects and assignments, so I'm not new to programming.  However, I'm having a really hard time trying to figure out how to work with MASM32 assembler (...in console mode  :'( ). I've already understood the very basics, but still, there is a lot for me to learn.

I'm having problems with dynamic memory allocation. The following code seems to work properly, but I have many questions about it.

  ;This is my very first dynamic memory attempt!
  ;
  ;theta is declared as "theta dword ?". I thought it could work as a pointer to byte
  ;stheta is the length of theta in bytes.
 
  ;We calculate the size in bytes of the Theta vector.
  ;num is a value input by the user. Theta's length = num +2

    mov eax,num
    add eax,2
    mov stheta,eax

  ;we allocate the memory  (...this seems to work, but am i doing it right?)  Is crt_malloc the appropriate function to do this?

    invoke crt_malloc, stheta
    mov theta,eax

  ;we tell the user what we just did

    print " - allocated "
    print uhex$(stheta), "h bytes for Theta, in adress "
    print uhex$(theta), endl

  ; BIG QUESTION :
  ; How can i read/write on theta?!
  ; For example, how can i move 230 (or 'A') onto the position i-th of the array?. I know it's something basic, but i have no clue about how to do it.


    invoke crt_free,theta

  ; How in the world does this work? i'm not giving "crt_free" any numerical value of the array's size, so either the array length is coded into the array (Pascal-like)
  ; and accessing certain positions  could mess things up, or it's stored somewhere else in my program.




Thanks in advance!!

GregL

JRevor,

You are doing everything correctly. I modified your code to answer your questions.


.686p
.MODEL FLAT,STDCALL
OPTION CASEMAP:NONE

INCLUDE \masm32\include\Windows.inc

INCLUDE \masm32\include\Kernel32.inc
INCLUDE \masm32\include\MSVCRT.inc
INCLUDE \masm32\include\Masm32.inc

INCLUDELIB \masm32\lib\Kernel32.lib
INCLUDELIB \masm32\lib\MSVCRT.lib
INCLUDELIB \masm32\lib\Masm32.lib

INCLUDE \masm32\macros\macros.asm

WaitKeyExit PROTO

PTRBYTE TYPEDEF PTR BYTE

.DATA

    num      DWORD    42h
    stheta   DWORD    0
    theta    PTRBYTE  0         ; DWORD is OK too
    endl     BYTE     13,10,0 

.CODE

  start:

  ;This is my very first dynamic memory attempt!
  ;
  ;theta is declared as "theta dword ?". I thought it could work as a pointer to byte
  ;stheta is the length of theta in bytes.

  ;We calculate the size in bytes of the Theta vector.
  ;num is a value input by the user. Theta's length = num +2

    mov eax, num
    add eax, 2
    mov stheta, eax

  ;we allocate the memory  (...this seems to work, but am i doing it right?)  Is crt_malloc the appropriate function to do this?

    invoke crt_malloc, stheta
    mov theta, eax

  ;we tell the user what we just did

    INVOKE crt_printf, SADD(" - allocated %Xh bytes for theta, at address %Xh",13,10), stheta, theta

  ; BIG QUESTION :
  ; How can i read/write on theta?!
  ; For example, how can i move 230 (or 'A') onto the position i-th of the array?. I know it's something basic, but i have no clue about how to do it.

    mov eax, theta
    mov ebx, 0
    mov BYTE PTR [eax+ebx], 65    ; mov 'A' to 1st byte
    inc ebx
    mov BYTE PTR [eax+ebx], 66    ; mov 'B' to 2nd byte
    inc ebx
    mov BYTE PTR [eax+ebx], 67    ; mov 'C' to 3rd byte
    inc ebx
    mov BYTE PTR [eax+ebx], 0     ; mov null to 4th byte
   
    INVOKE crt_printf, SADD("theta contains: %s",13,10), theta

    invoke crt_free, theta

  ; How in the world does this work? i'm not giving "crt_free" any numerical value of the array's size, so either the array length is coded into the array (Pascal-like)
  ; and accessing certain positions  could mess things up, or it's stored somewhere else in my program.


    INVOKE WaitKeyExit
   
    xor eax, eax
    INVOKE ExitProcess, eax
   
;------------------------------------
WaitKeyExit PROC
    .DATA
        szPrompt BYTE 13,10,"Press any key to exit ... ",0
        szCrLf   BYTE 13,10,0
    .CODE
        INVOKE StdOut, ADDR szPrompt
        INVOKE crt__getch
        .IF (eax == 0) || (eax == 0E0h)
            INVOKE crt__getch
        .ENDIF
        INVOKE StdOut, ADDR szCrLf
        xor eax, eax
        ret
WaitKeyExit ENDP
;------------------------------------   
END start


clive

Ok, crt stands for C runtime, these functions work in the same way as malloc() and free() in C

For example
Buffer = malloc(Size);

free(Buffer);

The memory is allocated from a much larger pool, and the management of that pool keeps track of the size and location of the block of memory. You can only release that block by passing the original address, so you can't increase the address and release a portion of it.

The equivalent of Buffer[3] = 'A'; would look like

 mov  esi,Buffer
 mov byte ptr [esi+3],041h

The equivalent of Buffer = 'B'; would look like

 mov  esi,Buffer
 mov  ebx,dword ptr i
 mov  byte ptr [esi + ebx],042h

-Clive
It could be a random act of randomness. Those happen a lot as well.

GregL

Clive,

The functions that are prefixed with crt_ actually are the C Run-Time Library functions. The prefix was added to avoid naming conflicts with the MASM32 library. msvcrt.lib is available on all versions of Windows from Windows 95B to Windows 7.

jj2007

#4
Quote from: clive on March 07, 2010, 02:04:54 AM
The equivalent of Buffer[3] = 'A'; would look like

 mov  esi,Buffer
 mov byte ptr [esi+3],041h


This shorter variant is also valid, EDIT: if buffer is a location in the .data section:

.data?
Buffer db 1000 dup(?)
.code
  mov Buffer[3], "A"


Use it if you want to move only one byte; otherwise, register+offset is a few bytes shorter.

hutch--

JRevor,

Ther are in fact a number of memory allocation strategies available in Windows and they tend to be tailored to fit different tasks so your choice is a lot wider than the C runtime methods which are provided out of the Windows API function calls in any case.

HeapAlloc()
VirtualAlloc()
GlobalAlloc()

Thenn more specialised versions, OLE string memory for both ANSI and UNICODE, a number of COM specific methods and with the three APIs mentioned there are variations on those as well.

It may sound messy but its very flexible and you can pick your way through the strategies that best fit your task once you are used to them.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

JRevor

#6
Thanks a lot for the reply, all of your responses have been really useful. Specially Greg Lyon's code, which cleared many of my doubts about dynamic memory.


Quote from: clive on March 07, 2010, 02:04:54 AM

The memory is allocated from a much larger pool, and the management of that pool keeps track of the size and location of the block of memory. You can only release that block by passing the original address, so you can't increase the address and release a portion of it.


Thanks for the explanation!

Quote from: hutch-- on March 07, 2010, 06:28:05 AM
JRevor,

Ther are in fact a number of memory allocation strategies available in Windows and they tend to be tailored to fit different tasks so your choice is a lot wider than the C runtime methods which are provided out of the Windows API function calls in any case.

HeapAlloc()
VirtualAlloc()
GlobalAlloc()

Thenn more specialised versions, OLE string memory for both ANSI and UNICODE, a number of COM specific methods and with the three APIs mentioned there are variations on those as well.

It may sound messy but its very flexible and you can pick your way through the strategies that best fit your task once you are used to them.

Definitely sounds interesting... maybe a bit too advanced for me. However, I won't forget to check them out, since those might be useful in the future.

I still have a couple more questions :

- Is there any macro to directly print a register/data as an unsigned decimal number ?
- Is there any macro/function to print certain bytes in a dynamic vector? (for instance, given the vector V = {A,B,C,D,E,F....} , print from 1 to 4, that is BCDE .
- Is there any "power" opcode? (for instance, to calculate a = 2^num)
(EDIT: Eventually I made my own natural power function, but i'm still curious to know if there's one already in the libraries)
- Is there any "memcpy"-like function? (to copy a certain ammount of bytes from one place to another)
- What if i do :

    mov eax, theta
    mov ebx, 0
    mov BYTE PTR [eax+ebx], something    ; something is a DWORD.

Am i copying only the first byte of "something" or the whole "something"?
- Is there any opcode to change the color of the text? (...it might sound stupid, but I want to mark relevant data in red)

Once again, thanks a lot!

MichaelW

QuoteIs there any macro to directly print a register/data as an unsigned decimal number ?

A combination of macros, yes. See the documentation for the print macro, and the string conversion macros str$, ustr$, hex$, uhex$, ubyte$, sbyte$, etc.

QuoteIs there any macro/function to print certain bytes in a dynamic vector? (for instance, given the vector V = {A,B,C,D,E,F....} , print from 1 to 4, that is BCDE .

For allocated memory you access the memory as an indirect memory operand and copy the value to a register, then display it. A simple example:

mov ebx, address
mov al, [ebx]
print xbyte$(al),13,10


Many variations are possible.

QuoteIs there any "power" opcode? (for instance, to calculate a = 2^num)

There is no "opcode" that I know of. For something easy you could call the crt pow function.

QuoteIs there any "memcpy"-like function? (to copy a certain ammount of bytes from one place to another)

There is the MASM32 MemCopy procedure, and various similar procedures that have been posted to the Laboratory, or the CRT memcpy or memmove functions.

Quote
What if i do :

mov eax, theta
mov ebx, 0
mov BYTE PTR [eax+ebx], something ; something is a DWORD.

Am i copying only the first byte of "something" or the whole "something"?

The MOV instruction, like most instructions, cannot take two memory operands, so something would need to be a register. The size of the transferred data would be the size of the register, and no ____ PTR would be necessary.

QuoteIs there any opcode to change the color of the text? (...it might sound stupid, but I want to mark relevant data in red)

No opcode, but for the console you should be able to change the color of existing text with the FillConsoleOutputAttribute function.
eschew obfuscation

JRevor


GregL

JRevor,

You can also use SetConsoleTextAttribute to change the color of any text written after the function call, here is a macro I wrote that uses it.


; ====================================
; Color Macro
; ====================================
; This macro uses the following equates
BLACK         EQU  0
DARKBLUE      EQU  1
DARKGREEN     EQU  2
DARKCYAN      EQU  3
DARKRED       EQU  4
DARKMAGENTA   EQU  5
DARKYELLOW    EQU  6
GRAY          EQU  7
DARKGRAY      EQU  8
BLUE          EQU  9
GREEN         EQU 10
CYAN          EQU 11
RED           EQU 12
MAGENTA       EQU 13
YELLOW        EQU 14
WHITE         EQU 15

Color MACRO fval:=<LIGHTGRAY>, bval:=<BLACK>
    IFNDEF hStdOut
        .DATA
            hStdOut DWORD 0
        .CODE
        INVOKE GetStdHandle, STD_OUTPUT_HANDLE
        mov hStdOut, eax
    ENDIF
     .CODE
        mov eax, bval
        shl eax, 4
        or  eax, fval
        INVOKE SetConsoleTextAttribute, hStdOut, eax
ENDM
; ====================================


fval is foreground, bval is background.

For red text: Color RED, BLACK or just Color RED

GregL

JRevor,

One thing forgot to mention is that the memory allocated with crt_malloc is full of junk, so after allocating the memory, if you want to clear it out to zeroes add a line INVOKE RtlZeroMemory, theta, stheta.




hutch--

JRevor,

As it looks like you are already using the masm32 macros, you can simplify memory allocation by using the "alloc" and "free" macros which work fine for general purpose memory allocation.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

Yeah, since he was already using crt_malloc and crt_free and seemed to be somewhat familiar with them, I just continued on using them.  Not that there is anything wrong with using them.  I wonder which Windows API function crt_malloc actually calls.




hutch--

Greg,

From a quick dis-assemble of the MSVCRT in my XP SP3 it all looks like the HeapAlloc() family of functions for "malloc".
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL