The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: JRevor on March 06, 2010, 11:47:02 PM

Title: Novice questions on dynamic memory
Post by: JRevor on March 06, 2010, 11:47:02 PM
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!!
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 07, 2010, 01:15:17 AM
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

Title: Re: Novice questions on dynamic memory
Post by: clive on March 07, 2010, 02:04:54 AM
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
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 07, 2010, 02:20:14 AM
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.
Title: Re: Novice questions on dynamic memory
Post by: jj2007 on March 07, 2010, 06:16:32 AM
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.
Title: Re: Novice questions on dynamic memory
Post by: 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.
Title: Re: Novice questions on dynamic memory
Post by: JRevor on March 07, 2010, 05:13:56 PM
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!
Title: Re: Novice questions on dynamic memory
Post by: MichaelW on March 07, 2010, 06:36:44 PM
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.
Title: Re: Novice questions on dynamic memory
Post by: JRevor on March 07, 2010, 07:19:01 PM
Fantastic answer, thanks a lot!!!
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 07, 2010, 08:21:47 PM
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
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 09, 2010, 01:57:03 AM
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.



Title: Re: Novice questions on dynamic memory
Post by: hutch-- on March 09, 2010, 03:33:21 AM
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.
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 09, 2010, 03:43:37 AM
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.



Title: Re: Novice questions on dynamic memory
Post by: hutch-- on March 09, 2010, 04:37:36 AM
Greg,

From a quick dis-assemble of the MSVCRT in my XP SP3 it all looks like the HeapAlloc() family of functions for "malloc".
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 09, 2010, 04:47:35 AM
Hutch,

That was quick!

Title: Re: Novice questions on dynamic memory
Post by: MichaelW on March 09, 2010, 05:33:41 AM
There is also crt_calloc, but at least under Windows 2000 it is amazingly slow, much slower than the combination of crt_malloc and RtlZeroMemory.

Title: Re: Novice questions on dynamic memory
Post by: dedndave on March 09, 2010, 10:45:24 AM
if you use HeapAlloc or GlobalAlloc, you have the option of clearing the allocated memory block
VirtualAlloc always initializes the allocated block to 0
Title: Re: Novice questions on dynamic memory
Post by: redskull on March 09, 2010, 01:08:06 PM
Quote from: dedndave on March 09, 2010, 10:45:24 AM
if you use HeapAlloc or GlobalAlloc, you have the option of clearing the allocated memory block
VirtualAlloc always initializes the allocated block to 0

No matter which method you use, pages on an NT system come back zeroed.  The heap will 'preinitialize' several pages for you during the process startup, which it fills with "baadcode" or "baadfood" or something else ridiculous, but any additional pages that get allocated will be zeroed.
Title: Re: Novice questions on dynamic memory
Post by: JRevor on March 09, 2010, 07:34:47 PM
Thanks a lot for the answers, I'm definitely learning a lot of stuff (Although, it's not compulsory to "zero" the memory dynamically allocated, and I normally don't do it. It's not difficult to keep track of what is garbage and what is not).

Seeing that this thread is still active, I'll ask another question on the same subject.

Why this code doesn't work at all?


;dwordbuffer is a DWORD, and contains a pointer to a zone within certain dynamically allocated
; memory which was previously accessed as [eax + ebx].

   mov dwordbuffer, eax
   add dwordbuffer,ebx
   ; I want to copy the content of msg5( a byte array declared in the .data section of my code)
   ;to the memory pointed by dwordbuffer
   invoke MemCopy,ADDR msg5,dwordbuffer,bytesRead ; CRASH!


EDIT: Also, this doesn't work either. Why?

invoke MemCopy,ADDR msg5,BYTE PTR[eax + ebx],bytesRead
Title: Re: Novice questions on dynamic memory
Post by: redskull on March 09, 2010, 08:42:03 PM
if my memory serves me, MemCpy takes the destination first, and then the source.
Title: Re: Novice questions on dynamic memory
Post by: jj2007 on March 09, 2010, 10:36:48 PM
The order is correct, src before dest. The byte ptr is the problem. Consider this code:
xor eax, eax
invoke MemCopy, dword ptr [eax + ebx], addr msg5, bytesRead
xor eax, eax
invoke MemCopy, byte ptr [eax + ebx], addr msg5, bytesRead
xor eax, eax


In Olly, you see it as follows:
0040102E       |.  33C0                     xor eax, eax
00401030       |.  FF35 00204000            push dword ptr [402000]
00401036       |.  68 18204000              push 00402018                      ;  ASCII "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - OK?"
0040103B       |.  FF3403                   push dword ptr [ebx+eax]
0040103E       |.  E8 2D000000              call 00401070
00401043       |.  33C0                     xor eax, eax
00401045       |.  FF35 00204000            push dword ptr [402000]
0040104B       |.  68 18204000              push 00402018                      ;  ASCII "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - OK?"
00401050       |.  66:6A 00                 push 0
00401053       |.  8A0403                   mov al, [ebx+eax]
00401056       |.  66:0FB6C0                movzx ax, al
0040105A       |.  66:50                    push ax
0040105C       |.  E8 0F000000              call 00401070

Note the rather odd mov al, [] etc sequence? Masm tries to push the "address" in the byte at [eax+ebx]. 8 bits is a bit short, or rather: 24 bits short of a real 32-bit address ;-)

Here is the working example:
include \masm32\include\masm32rt.inc

.data?

.data
bytesRead dd SIZEOF AppName
AppAddress dd AppName
AppName db "Masm32 is great", 0
msg5 db 100 dup("x")

.code

start:
mov eax, offset AppAddress
xor ebx, ebx
invoke MemCopy, dword ptr [eax + ebx], addr msg5, bytesRead
print offset msg5, " - OK?"
exit
end start
Title: Re: Novice questions on dynamic memory
Post by: JRevor on March 11, 2010, 04:28:24 PM
EDIT:  Thanks a lot for your responses!

 I was really surprised that my code didn't work using BYTE PTR, because Greg used it in his code, and it worked perfectly. However, there was something wrong with my code. Somewhere in the procedure the adress eax was pointing to got changed (probably because a function returne a value in eax ), so i ended up accessing the wrong memory adress. That's why i had an error!.

By the way, is there any debugger for masm32 you'd recommend?
Title: Re: Novice questions on dynamic memory
Post by: jj2007 on March 11, 2010, 04:46:48 PM
Most of us use OllyDbg (http://www.ollydbg.de/).
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 11, 2010, 06:19:11 PM
JRevor,

I used BYTE PTR in my code because I was working with BYTEs.  With MemCopy you are working with DWORDs.

Title: Re: Novice questions on dynamic memory
Post by: JRevor on March 12, 2010, 02:19:58 PM
Quote from: Greg Lyon on March 11, 2010, 06:19:11 PM
JRevor,

I used BYTE PTR in my code because I was working with BYTEs.  With MemCopy you are working with DWORDs.



Okay, thanks for the answer.
Anyways, I ended up making my own memcopy  :lol
Title: Re: Novice questions on dynamic memory
Post by: GregL on March 12, 2010, 06:43:45 PM
Quote from: JRevorAnyways, I ended up making my own memcopy

Good  :U