The MASM Forum

General => The Campus => Topic started by: LoveToLrn on December 04, 2013, 02:08:00 PM

Title: Some basic help
Post by: LoveToLrn on December 04, 2013, 02:08:00 PM
Hi Guys! I am new to the forum and MASM32 development environment but I am loving it and the community on this forum already.
My question pertains mainly to a problem I am having with assembling and linking basic programs. For some reason when I try to
"Console Assemble and Link" the following code, I get this error:

"error LNK2001: unresolved external symbol _main"



code:
Quote
.486
.MODEL flat

.code
main:
    mov eax,0FFFFFFFFh
END main
I have been able to get other examples to run, but for some reason these basic ones won't link.
I am trying to focus on 32-bit code currently. I am coming from writing my basic assembly programs in Visual Studio 2012.
Any help is appreciated, Thanks in advance everyone!
Title: Re: Some basic help
Post by: Siekmanski on December 04, 2013, 02:26:48 PM
Welcome  LoveToLrn,


    .486
    .model      flat,stdcall
    option      casemap:none

    include     windows.inc
    include     user32.inc
    includelib  user32.lib
    include     kernel32.inc
    includelib  kernel32.lib

.data
; your data here

.code
; your subroutines here

start: ; starting point of your program

    invoke  ExitProcess,0
end start


Have you downloaded the masm32 SDK?  http://masm32.com/masmdl.htm
It has a lot of examples.
Title: Re: Some basic help
Post by: LoveToLrn on December 04, 2013, 02:32:43 PM
Yes I downloaded the whole package I believe. I wasen't sure if I was missing any "mission critical" code like those includes,
looking at them I can see what I missed, thanks very much Siekmanski!  :biggrin:
Title: Re: Some basic help
Post by: dedndave on December 04, 2013, 02:41:40 PM
that specific error is probably related to the missing line
  .MODEL Flat,StdCall

terminating with ExitProcess is also a nice idea
but, i can understand what you were doing - you eliminated all the externals

the processor, model, casemap option, and includes can all be done with one line
    INCLUDE     \Masm32\Include\Masm32Rt.inc
that is a plain ASCII text file that you can open and examine with NotePad
it covers the most-often used includes and libraries
Title: Re: Some basic help
Post by: LoveToLrn on December 04, 2013, 02:48:16 PM
OH! Thanks for the tip dedndave! Can I modify the text file with my own libs/includes?
Title: Re: Some basic help
Post by: dedndave on December 04, 2013, 02:51:56 PM
you can, but i don't recommend it   :eusa_naughty:
Title: Re: Some basic help
Post by: dedndave on December 04, 2013, 02:55:01 PM
just add any additional includes and/or includelibs after that line
    INCLUDE     \Masm32\Include\Masm32Rt.inc
    .586
    INCLUDE     \Masm32\Include\AdvApi32.inc
    INCLUDELIB  \Masm32\Lib\AdvApi32.lib


and - anything that's in there that your program does not use won't affect the size of the EXE

the reason i don't recommend it.....

you won't be compatible with all the code posted in the forum
when someone else tries to build your project - bang - errors
same when you try to build someone else's

EDIT: i also added a bump in the processor from 486 to 586
Title: Re: Some basic help
Post by: LoveToLrn on December 04, 2013, 03:01:30 PM
Ok, good point, thanks  :biggrin:
Also is your .586 directive just a more recent version of the processor model than .386, or .486 for that matter?
Is there any benefit to specifying a more recent processor model number beyond .386?
Title: Re: Some basic help
Post by: dedndave on December 04, 2013, 03:07:13 PM
yes there is
it allows you to use the newer pentium instructions and instruction forms
one example that comes to mind is the RDTSC instruction, but there are others

also, if you want to use SIMD instructions....
    .686
    .MMX
    .XMM


i think the masm version that is in the masm32 package goes as far as SSE2 extensions
you can find newer versions of the assembler that can handle SSE3, 4, etc
also, JwAsm is a free assembler that handles them and is nearly 100% compatible with masm
Title: Re: Some basic help
Post by: LoveToLrn on December 04, 2013, 03:09:59 PM
Awesome, Thanks for the info!
I am not as far along as SIMD but hope to be writing more complex programs soon.
I think you guys and this forum as a whole will be a HUGE boost! Very glad I found it. :biggrin:
Title: Re: Some basic help
Post by: dedndave on December 04, 2013, 03:11:02 PM
try this program
assemble as console mode
        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .List

;###############################################################################################

;initialized data section

        .DATA

szMessage db 'Hello World !',0

;***********************************************************************************************

;uninitialized data section

        .DATA?

dwSomeVal dd ?

;###############################################################################################

;code section

        .CODE

;***********************************************************************************************

_main   PROC

        print   offset szMessage

        print   chr$(13,10)
        inkey
        INVOKE  ExitProcess,0

_main   ENDP

;###############################################################################################

        END     _main
Title: Re: Some basic help
Post by: LoveToLrn on December 04, 2013, 03:36:07 PM
I tried it out, I was wondering how to pass a wait message to the console! Thanks  :biggrin:
Also didn't know there was a .data segment for uninitialized variables.
Title: Re: Some basic help
Post by: hamper on December 04, 2013, 10:39:50 PM
Quote from: LoveToLrn on December 04, 2013, 03:36:07 PM
Also didn't know there was a .data segment for uninitialized variables.
There isn't. The data segments are...

.const
Here you define any global constant data such as integer constants, string constants and floating point constants etc.

.data?
Here you define uninitialised global variables such as general variables, arrays and structures etc. Memory is reserved but not initialised.

.data
Here you define initialised global variables such as general variables, arrays and structures etc. Memory is reserved and initialised.
Title: Re: Some basic help
Post by: jj2007 on December 05, 2013, 01:06:03 AM
Quote from: hamper on December 04, 2013, 10:39:50 PM
.data?
Here you define uninitialised global variables such as general variables, arrays and structures etc. Memory is reserved but not initialised.

That is the "official" version. Truth is the OS initialises them to zero - in contrast to local variables, which are really not initialised, i.e. a space is reserved for them on the stack, but it will contain garbage.
Title: Re: Some basic help
Post by: 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.
Title: Re: Some basic help
Post by: Magnum on December 05, 2013, 12:29:16 PM

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
Title: Re: Some basic help
Post by: jj2007 on December 05, 2013, 07:11:50 PM
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 (http://en.wikipedia.org/wiki/Data_segment#BSS):
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 (http://www.ollydbg.de/version2.html), 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 (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1151) 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 (http://findbugs%20for%20assembler) 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)
Title: Re: Some basic help
Post by: FORTRANS on December 06, 2013, 12:41:11 AM
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.