News:

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

Main Menu

GlobalAlloc

Started by dc, September 01, 2023, 06:06:11 AM

Previous topic - Next topic

dc

im trying to use this from c++ in masm32:
             lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
so far i got this:
        push 100
        push GMEM_FIXED
        call dword ptr [GlobalAlloc]
        mov  lpBits,eax

it assembles fine, but...
it crashes the program...
any idea what's wrong?
i used a disassembly of another prog to see how this might work

NoCforMe

Not the solution to your problem, but why not simplify things? Use this instead of "push-push-call":

    INVOKE    GlobalAlloc, GMEM_FIXED, 100

Also, are you sure you want to use GlobalAlloc() and not some other memory-allocation function? Micro$oft has this to say about it:

QuoteNew applications should use the heap functions to allocate and manage memory unless the documentation specifically states that a global function should be used. For example, the global functions are still used with Dynamic Data Exchange (DDE), the clipboard functions, and OLE data objects.

Still, it looks like what you wrote should work ... [edits after JJ's reply] ... ASSUMING 1) 100 bytes is enough to hold whatever you're trying to put in there, and 2) not sure why you used the construct [GlobalAlloc] rather than just the function name.

Anyhow, what JJ said ...
Assembly language programming should be fun. That's why I do it.

jj2007

Hi dc,

As NoCforMe already pointed out, a simple invoke GlobalAlloc, GMEM_FIXED, 100 will do the job. However, I have a little doubt whether 100 bytes are enough for an image. Is that really the size?

You should zip your complete source and executable and attach it to the next post, so that we can help you better.

Caché GB

Hi dc

The reason your code crashes is becouse you are trying to dereference the
address of the GlobalAlloc function by doing this

        call dword ptr [GlobalAlloc]

Just call it the proper way

        call GlobalAlloc
Caché GB's 1 and 0-nly language:MASM

dc

im trying to save a bitmap that was created with CreateCompatibleBitmap
im getting the snippet here:
https://learn.microsoft.com/en-us/windows/win32/gdi/storing-an-image
it's not large enough just simplified for experimenting
in the example they seem to get a pointer instead of a handle and it's got me stumped

dc

i got this from dissassembling some other app:
00409382 8B4608                 mov     eax,[esi+8]
00409385 C1E004                 shl     eax,4
00409388 83C008                 add     eax,8
0040938B 50                     push    eax
0040938C 6A02                   push    2
0040938E FF151CF24D00           call    dword ptr [GlobalAlloc]

dc

i cant get a handle to work like a pointer when i just invoke it

Vortex

Hi dc,

Here is a small command-line tool saving your desktop as a bitmap file, maybe it can be useful for you :

SaveDesktop.exe MyDesktop.bmp

SaveDesktop.exe MyDesktop2.bmp 32

The second option saving the bitmap as 32-bit

Edit : It's easier to study the official documentation than trying to figure out disassembled code :

https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalalloc

NoCforMe

As @Caché GB pointed out, don't try to dereference the function pointer.

And don't just plop debugger-displayed code in your source. Apples and oranges. This won't work:

0040938E FF151CF24D00          call    dword ptr [GlobalAlloc]

As @Caché GB stated, just use

CALL GlobalAlloc

Or better yet just use INVOKE GlobalAlloc ...
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: dc on September 01, 2023, 06:42:34 AMi cant get a handle to work like a pointer when i just invoke it

Sounds like you're learning a very important lesson for Win32 programming: the difference between a handle and a pointer.

Let's take memory allocation using the heap functions:

  • To start, you need to use GetProcessHeap() to get a handle to the heap.
  • To actually allocate memory using this handle, use HeapAlloc(), which returns a pointer to the allocated memory.

This is just one example (though I would highly recommend that you use the heap-allocation stuff rather than GlobalAlloc(), even though that one MS example used it). If you read the Microsoft (or other) documentation carefully, it'll tell you whether you're getting a handle or a pointer back. As you're discovering, the two are not interchangeable! A handle will never "work like a pointer", and vice versa.

(Ackshooly, hopefully not to confuse you, but a handle is a pointer, except that it points to some internal data structure inside Windows that we, as programmers, really aren't supposed to know about nor mess with. So it's not a pointer in the sense that you can use it to access, say, an array of data (bytes/words/dwords, whatever). So don't get the two mixed up!)
Assembly language programming should be fun. That's why I do it.

dc

thanx guys, ill try this stuff out...

dc

#11
i get 0 from GetDIBits() and last error says it succeeded...
i think i should get return of 1080...

savepic proc
local bmp:BITMAP
local bmi:BITMAPINFO
local pbmi:PTR BITMAPINFO
local pclrs:DWORD
local prgb:DWORD
local cClrBits:WORD
local hf:HANDLE
local hdr:BITMAPFILEHEADER
local pbih:PBITMAPINFOHEADER
local lpBits:LPBYTE
local dwTotal:DWORD
local cb:DWORD
local php:PTR BYTE
local dwTmp:DWORD
local pbi:PTR BITMAPINFO
local hheap:HANDLE
local pbmp:PTR BITMAP
        lea eax,bmp
        mov pbmp,eax
        vk BeginPaint,hwnd,addr ps
        mov hdc,eax
        vk CreateCompatibleDC,hdc
        mov hdct,eax
        vk SelectObject,hdct,hbmpt

        ;   CreateBitmapInfoStruct
        mov esi,pbmp
        ASSUME esi:ptr BITMAP
        vk GetObject,hbmpt,sizeof BITMAP,esi    ;   get color format & dims
        mov cClrBits,24
        m2m bmi.bmiHeader.biSize,sizeof BITMAPINFOHEADER
        vk GetProcessHeap
        mov hheap,eax
        vk HeapAlloc,hheap,HEAP_NO_SERIALIZE,sizeof BITMAPINFO
        mov pbmi,eax
        mov esi,eax
        ASSUME esi:ptr BITMAPINFO
        m2m [esi].bmiHeader.biWidth,bmp.bmWidth
        m2m [esi].bmiHeader.biHeight,bmp.bmHeight
        m2m [esi].bmiHeader.biPlanes,bmp.bmPlanes
        m2m [esi].bmiHeader.biBitCount,bmp.bmBitsPixel
        m2m [esi].bmiHeader.biClrUsed,eax
        mov [esi].bmiHeader.biCompression,BI_RGB
        mov eax,[esi].bmiHeader.biWidth
        add eax,7
        divid 8
        mult [esi].bmiHeader.biHeight
        xor ecx,ecx
        mov cx,cClrBits
        xor edx,edx
        mul ecx
        mov [esi].bmiHeader.biSizeImage,eax

        ;   CreateBMPFile
        vk HeapAlloc,hheap,HEAP_NO_SERIALIZE,[esi].bmiHeader.biSizeImage
        mov lpBits,eax
        ASSUME eax:ptr LPBYTE




        vk GetDIBits,hdct,hbmpt,0,[esi].bmiHeader.biHeight,lpBits,pbmi,DIB_RGB_COLORS



        vk HeapFree,hheap,HEAP_NO_SERIALIZE,lpBits
        vk HeapFree,hheap,HEAP_NO_SERIALIZE,pbmi
        vk HeapDestroy,hheap
        vk DeleteDC,hdc
        vk DeleteDC,hdct
        vk EndPaint,hwnd,addr ps
    Ret
savepic EndP

RESOLVED... a line was oout of place... oops
NOPE... NOT RESOLVED...
still getting return 0

jj2007

Quote from: NoCforMe on September 01, 2023, 06:57:57 AM(Ackshooly, hopefully not to confuse you, but a handle is a pointer, except that it points to some internal data structure inside Windows that we, as programmers, really aren't supposed to know about nor mess with. So it's not a pointer in the sense that you can use it to access, say, an array of data (bytes/words/dwords, whatever). So don't get the two mixed up!)

GlobalAlloc is a special case here:
  invoke GlobalAlloc, GMEM_FIXED, 100       ; eax is a pointer to the memory block
  mov ptr1, eax
  invoke GlobalAlloc, GMEM_MOVEABLE, 100    ; eax is a handle to a memory object
  mov handle, eax
  invoke GlobalLock, handle        ; To translate the handle into a pointer, use GlobalLock
  mov ptr2, eax
  ; ... do useful things with ptr2 ...
  invoke GlobalUnlock, handle        ; release the pointer (but not the memory object)
  invoke GlobalFree, handle          ; release the memory object
  invoke GlobalFree, ptr1            ; release the memory object

When monitoring the handle and the pointers, you would typically get something like this:
handle          3538948
ptr1            6608584
ptr2            6608712

Handle and pointers sit in different memory areas.

For 90% of all uses, GMEM_FIXED does the job: you get a pointer directly. The exceptions are the clipboard, DDE, and OLE objects:
QuoteNew applications should use the heap functions to allocate and manage memory unless the documentation specifically states that a global function should be used. For example, the global functions are still used with Dynamic Data Exchange (DDE), the clipboard functions, and OLE data objects.

dc

thanx... funny how it can be so difficult to get info like that...
have a funny day

NoCforMe

Quote from: dc on September 01, 2023, 10:31:12 PMthanx... funny how it can be so difficult to get info like that...

Au contraire, my friend: learn.microsoft.com is your friend. All the info you need is there.

Well, there and also Stack Overflow, Code Project, etc. (You might want to look at Raymond Chen's excellent blog, The Old New Thing.)
Assembly language programming should be fun. That's why I do it.