Announcement

Collapse
No announcement yet.

What are Stack and Heap ?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    Originally posted by Rodney Hicks View Post
    FWIW my results for 10 runs of the code in posts 14 and 15:
    144, 168, 48, 24, 120, -120, 96, -144, 96, 48
    Win 10 32 bit
    All multiples of 24, that make sense.

    But logically two variables initialised with a single character one after the other with nothing happening prior to or between the assignments should be in consecutive memory blocks. The interesting question is why the numbers different from run to run. (From this small sample of 3 an initial hypothesis is that it is happening on 32bit windows but not on 64bit). Are the intermediate blocks of 24 bytes being used or is the behind the scenes memory allocation doing something else?

    Are these varying numbers the result of multiple runs with the same compiled application or with multiple compilations?

    Comment


    • #22
      what a great question and answers!

      Comment


      • #23
        Multiple compilations of the code. I've no idea why it is done this way. Maybe if it has almost all program memory tied up it might change its ways, but I doubt it.
        Rod
        I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

        Comment


        • #24
          FWIW I see the same as Rod on Win10 64bit and the same as Stuart on Win7 64bit
          Rgds, Dave

          Comment


          • #25
            Originally posted by Dave Biggs View Post
            FWIW I see the same as Rod on Win10 64bit and the same as Stuart on Win7 64bit
            Ah-ha. I'm on Win7. So it looks like Win version not "bitness" that makes the difference.

            Comment


            • #26
              The terms stack and heap are wider than any particular programming language dialect. In Win32 the stack is defined in the executable file format and is usually 1 meg by default. At the programmer level the stack is memory where you pass arguments to and allocate local variables within a procedure. As part of the OS definition you have a few options, a procedure with a stackframe or without a stack frame and this is controlled by 1 or 2 registers, EBP and ESP, respectively the base pointer and the stack pointer. Depending on if you use a stackframe or not, when a procedure makes a CALL to another it pushes the return address onto the stack, literally stack memory, pushes argument after that and if LOCAL variables are required, it shifts the stack pointer ESP or with a stack frame EBP to make room for the LOCAL variables.

              On exit from a procedure, the stack must be balanced so you have a RET followed by the byte count of the arguments so the stack pointer is returned back to where it was when the procedure was called. This is why LOCAL variables only have scope while the procedure is running, the stack space is overwritten on exit and the variables no longer exist. Normally a LOCAL variable is uninitialised at entry as its contents are junk left on the stack and some languages (PB included) initialise the LOCAL variables to 0 fill (the number, not the character) at startup. You have the option in PB for advanced code to use a FASTPROC which has no stack frame unless you want to write one.

              System memory, what Stuart is calling the "heap" is a different animal, its a pool of memory that is allocated by the OS on demand with a number of system API functions, HeapAlloc(), GlobalAlloc(), VirtualAlloc() and in the case of basic string memory, SysAllocStringByteLen() which is an OLE format that works like an old PASCAL string where you have the length of the string stored in the first 4 bytes and the string data stored directly after it. While it is hidden from the basic programmer, the basic string engine handles all of the allocation and freeing of basic string memory but it is allocated memory which must be allocated and freed.

              That is the distinction between STACK and HEAP as the question was originally asked, to the programmer, stack memory is transient and automatically made available where system memory must be allocated and freed. In basic at close range, LOCAL and GLOBAL will do the same thing, you can write data to an from such variables, its just that they are created differently with different scope.
              hutch at movsd dot com
              The MASM Forum

              www.masm32.com

              Comment


              • #27
                LOCAL variables are allocated on the stack.
                BUT dynamic string variables come in 2 parts.

                The variable itself is on the stack and contains a pointer to the string data. You get this value with VARPTR().
                The string data location is allocated by the OS and is not on the stack. You get this value with STRPTR() and it can change when the string data is changed.

                It's the same as allocating pointers.
                A LOCAL pointer will be on the stack and will be 32 bits but the data it points to could be anywhere and any size.

                The local STRING data is just a pointer and is 4 bytes long so successively declared local STRINGs will usually have addresses differing by 4 and will be located on the stack.
                These point to the content of the string and the string length but it's up to the OS to allocate that and it can vary in size and location and you just have to accept what the OS returns.

                Comment


                • #28
                  PS If you want to know where the stack pointer is pointing, you can get it like this:


                  LOCAL StackPointer AS LONG

                  !mov StackPointer,ESP

                  Comment


                  • #29
                    Originally posted by Stuart McLachlan View Post
                    All multiples of 24, that make sense.

                    But logically two variables initialised with a single character one after the other with nothing happening prior to or between the assignments should be in consecutive memory blocks.
                    Doh! I wasn't thinking it through.
                    The pointer addresses are Virtual addresses, not memory locations.

                    (MCM is the only poster so far who has actually drawn attention to the difference between virtual addresses and memory locations)

                    Comment


                    • #30
                      Make a change to the string's length and see if "24" is still true. Heck, see if any number remains true.

                      The only way you can get the value of the pointer to a dynamic string's string data is to use the STRPTR function after the last time the string was changed.

                      Michael Mattias
                      Tal Systems Inc. (retired)
                      Racine WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #31
                        Originally posted by Michael Mattias View Post
                        Make a change to the string's length and see if "24" is still true. Heck, see if any number remains true.

                        The only way you can get the value of the pointer to a dynamic string's string data is to use the STRPTR function after the last time the string was changed.
                        Irrelevant

                        Comment


                        • #32
                          Thank you Everyone, learn much from here

                          Comment


                          • #33
                            Not only Irrelevant.
                            '
                            Code:
                            #compile exe
                            #dim all
                            
                            function pbmain () as long
                              local MyStr as string
                              local spMyStr, vpMyStr, x as dword
                              MyStr = "blah, blah, brown fox ... "
                              spMyStr = strptr(MyStr)
                              vpMyStr = varptr(MyStr)
                              x = peek(dword, vpMyStr)
                              ? str$(spMyStr) + $crlf + _
                                str$(vpMyStr) + $crlf + _
                                str$(x)
                            end function '
                            When I run this spMyStr and x are the same.

                            "... after the last time the string was changed." is true.
                            Last edited by Dale Yarker; 25 Jul 2020, 06:48 PM.
                            Dale

                            Comment


                            • #34
                              One more try. A short demo on what the stack is doing via the two registers used in construction procedures (subs and functions in basic).
                              Code:
                              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              
                                  #include "\basic\include\win32api.inc"
                              
                                  GLOBAL rESP as DWORD
                                  GLOBAL rEBP as DWORD
                              
                                  MACRO showstack(UserString)
                                    ! mov rESP, esp
                                    ! mov rEBP, ebp
                                    StdOut "  esp = "+format$(rESP)+" ebp = "+format$(rEBP)+" "+UserString+$CRLF
                                  END MACRO
                              
                              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              
                              FUNCTION PBmain as LONG
                              
                                  LOCAL cnt as DWORD
                              
                                  showstack("stack at App entry")
                              
                                  ! call nops                             ' call an empty FASTPROC
                              
                                  showstack("stack at FASTPROC exit")
                              
                                  cnt = numz                              ' call a basic function
                              
                                  showstack("Balanced stack on FUNCTION exit")
                              
                                  waitkey$
                              
                              End FUNCTION
                              
                              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              
                              FUNCTION numz() as DWORD
                              
                                  LOCAL x1 as DWORD
                                  LOCAL x2 as DWORD
                                  LOCAL x3 as DWORD
                                  LOCAL x4 as DWORD
                              
                                  showstack("FUNCTION entry")
                              
                                  x1 = 1
                                  x2 = 2
                                  x3 = 3
                                  x4 = 4
                              
                                  showstack("FUNCTION exit")
                              
                                  FUNCTION = x1 + x2 + x3 + x4
                              
                              End FUNCTION
                              
                              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              
                              FASTPROC nops
                              
                                  showstack("FASTPROC entry - ESP 4 bytes lower than caller due to CALL")
                              
                                  ! nop
                                  ! nop
                                  ! nop
                                  ! nop
                                  ! nop
                                  ! nop
                                  ! nop
                                  ! nop
                              
                                  showstack("FASTPROC exit")
                              
                                  ! ret
                              
                              END FASTPROC
                              
                              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              It display results like this.
                              Code:
                                esp = 1703444 ebp = 1703600 stack at App entry
                              
                                esp = 1703440 ebp = 1703600 FASTPROC entry - ESP 4 bytes lower than caller due to CALL
                              
                                esp = 1703440 ebp = 1703600 FASTPROC exit
                              
                                esp = 1703444 ebp = 1703600 stack at FASTPROC exit
                              
                                esp = 1703268 ebp = 1703436 FUNCTION entry
                              
                                esp = 1703268 ebp = 1703436 FUNCTION exit
                              
                                esp = 1703444 ebp = 1703600 Balanced stack on FUNCTION exit
                              hutch at movsd dot com
                              The MASM Forum

                              www.masm32.com

                              Comment


                              • #35
                                And just in general.. ..

                                Not needing to be concerned with detail management of the stack and the heap is why you paid good money for a compiler license.
                                Michael Mattias
                                Tal Systems Inc. (retired)
                                Racine WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #36
                                  I am more inclined to respect the asker of the original question, you may not need the "zen" of electron flow to understand what a computer is inclined to do but some like to know how things work. PB does do all of those things #STACK settings, can allocate memory from the system that some call the "heap". The field of computing is so wide that no-one know it all and most just pick what they are interested in and as programmers, write what they need.

                                  I don't have any particular bias, line numbered code works, pure HEX works, intrinsic basic works, asm works and APIs work, the only factor I see as important is if the end results works.
                                  hutch at movsd dot com
                                  The MASM Forum

                                  www.masm32.com

                                  Comment


                                  • #37
                                    don't have any particular bias, line numbered code works, pure HEX works, intrinsic basic works, asm works and APIs work, the only factor I see as important is if the end results works.
                                    Have you forgotten so soon? It's not the paintbrush, it's the artist!
                                    Michael Mattias
                                    Tal Systems Inc. (retired)
                                    Racine WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment


                                    • #38
                                      I take your point but you must have some give in both directions. The Mona Lisa would not have become famous if it was done with a thumbnail dipped in tar but likewise a amateur with a pallette and the brushes and paint of a master will still mess it up. Another factor is most of the old masters made their own tools, something that an amateur would not know how to do.
                                      hutch at movsd dot com
                                      The MASM Forum

                                      www.masm32.com

                                      Comment

                                      Working...
                                      X