News:

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

Main Menu

Some basic help

Started by LoveToLrn, December 04, 2013, 02:08:00 PM

Previous topic - Next topic

Magnum


The development of these languages involved a design philosophy in which conflicts between performance and safety were generally resolved in favor of performance. The programmer was given the burden of being aware of dangerous issues such as uninitialized variables.


What is so dangerous about uninitialized variables ?

I am assuming that the programmer is consciences and sets it properly before using it.

Do some operating systems set it to zero in case the programmer boofed up ?

Andy
Take care,
                   Andy

Ubuntu-mate-18.04-desktop-amd64

http://www.goodnewsnetwork.org

jj2007

Quote from: hamper on December 05, 2013, 05:08:03 AM
I knew that was the situation under C, where uninitialised global variables are automatically initialised to zero (for numeric) or nul (each byte of a character or string), and uninitialised local variables of any type are not automatically initialised at all (so their memory locations will still contain whatever was there already), but I didn't know whether this was the case under assembly language as well. Guess I'll have to check this out and update my notes accordingly. Thanks for the info.

It's somehow difficult to find proper documentation for the fact that the .data? contains zeroes on program start. Wiki says:
QuoteThe BSS segment, also known as uninitialized data, starts at the end of the data segment and contains all global variables and static variables that are initialized to zero or do not have explicit initialization in source code. For instance a variable declared static int i; would be contained in the BSS segment.
Heap

The heap area begins at the end of the BSS segment and grows to larger addresses from there.

Just in case a newbie reads this, let's be a bit more explicit:
_bss segment
myvar   dd ?

and
.data?
myvar   dd ?

do exactly the same: they mark the beginning of the uninitialised data segment.

In fact, it is not C but Windows who cares about zeroing the .data? segment, so assembly code automatically enjoys the same treatment, i.e. zeroed variables that don't increase the size of the executable ("bss = better save space").

In contrast, local variables are created on the stack by one simple instruction: sub esp, size_of_locals (the PROLOGUE macro knows the total size required for local variables and takes care to reserve it on the stack with this instruction).

As you can see in Olly, on top of a proc there is not the faintest effort to zero the space created with sub esp, xxx; so if the stack has been used elsewhere in your code, it may contain values of pushed variables, return addresses etc, and occasionally also zeros.

In case you want to use these variables to assign values to them, no problem. If, however, your code assumes that they are zero, you might run into trouble. Take this simple example:

include \masm32\include\masm32rt.inc

.code
start:
        call foo
        inkey chr$(13, 10, "Nice, isn't it?")
        exit

foo proc uses esi edi ebx Arg1, Arg2
LOCAL ct
        ; a ClearLocals macro would be nice ;-)
        .Repeat
                inc ct
                print "*"
        .Until ct==50
        ret
foo endp

end start


Just test it - you will see a long line of stars. Great, isn't it? Now test the same inside a bigger application, and you'll see how your screen fills up with stars. If you have a console, that is - a GUI app will just hang, or maybe it won't, it really depends on what kind of garbage fills the variable "ct" at that particular moment. In any case, you have a ticking bomb in your code...

There was a dedicated "FindBugs for Assembler" thread some time ago, which treated the uninitialised locals issue, too.

P.S.: In case this is not yet confusing enough: In C, you can use the static keyword for local variables:
#include <stdio.h>

void PrintCt (void) {
  static int ct=0; // WOW, a "static" local variable...
  ct++;
  printf("%i ", ct);
  }

int main(void) {
PrintCt();
PrintCt();
PrintCt();
return 0;
}


Guess what it will output 8)

FORTRANS

Hi,

   It is the operating system that zeroes out uninitialized memory
on program load for security reasons.  Or fills it with some other
value.  When I was programming in FORTRAN on a CDC mainframe,
uninitialized variables were set to an illegal value if used by a real
(floating point) calculation.  (Boom, end of program.)  When used
in an integer calculation, (I think) it just produced a garbage result.

Regards,

Steve N.