News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Why MASM doesn't assemble this?

Started by sb1370, April 28, 2013, 05:26:43 PM

Previous topic - Next topic

sb1370

Hi;
Our teacher uses a syntax like this simple example for teaching assembly:

.MODEL SMALL
.386
.DATA
X DB 3
.CODE
.STARTUP
MOV AL,5
ADD AL,X
.EXIT
END


I tried this for MASM:
.MODEL SMALL
.386
.DATA
X DB 3
.CODE
main:
MOV AL,5
ADD AL,X
end main
.EXIT
END

But MASM doesn't assemble this. :(
What's the problem?
He usually uses emu8086 but it's a bit old and I want to do this with MASM.

jj2007

Quote from: sb1370 on April 28, 2013, 05:26:43 PM
But MASM doesn't compile this. :(

Masm is not a compiler, it's an assembler. And it does assemble your snippet. Probably (can't read your thoughts, can't see your error messages) you'll see complaints from the linker. Are you using \Masm32\bin\link16.exe ?

japheth

Quote from: sb1370 on April 28, 2013, 05:26:43 PM
But MASM doesn't compile this. :(
What's the problem?

The more important question that you should ask yourself is why you want to remove .STARTUP and .EXIT. Because these directives are there for a good reason and they can't just be removed without causing your program to crash when it's launched.

QuoteHe usually uses emu8086 but it's a bit old and I want to do this with MASM.

Masm is most likely older than emu8086.

dedndave

it does assemble using MASM, although both versions have little problems   :P

both versions use a .END directive, but do not reference the entry point
your version doesn't initialize the DS register, nor does it terminate properly

as Jochen mentioned, this is 16-bit code and will build if you use a 16-bit linker

i have never used the .STARTUP or .EXIT directives, so i was curious to see exactly what they do
i figured the .STARTUP directive sets the DS register and .EXIT terminates with INT 21h
well, i was half-right   :P

.EXIT generates the following code, at least when the SMALL model is specified
        mov     ah,4Ch
        int     21h

it may generate something different if the TINY model is specified

the code generated by .STARTUP was a little more surprising
again, this is for a SMALL model program and it undoubtedly generates something different for other models
        mov     ax,@data
        mov     ds,ax

        mov     bx,ss
        sub     bx,ax
        shl     bx,4
        mov     ss,ax
        add     sp,bx

the first 2 lines are pretty simple
they load the data segment into AX, then into DS - very common code for 16-bit EXE's

the rest of the code forces the SS register to reference the same segment as the DS register
a bit of a mystery for a beginner, probably
but it's forcing the .DATA segment and .STACK segment into a single GROUP
not really sure why they do that - it isn't necessary, in many cases

personally, i would write the program to look something like this...
;###############################################################################################

        .MODEL  SMALL
        .386

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

        .DATA

X       db 3

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

        .CODE

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

_main   PROC    FAR

        mov     ax,@data
        mov     ds,ax

        MOV     AL,5
        ADD     AL,X

        mov     ah,4Ch
        int     21h

_main   ENDP

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

        END     _main

i would also add a couple other directives, but that's beyond what the teacher wants
you could replace the first 2 lines of code with .STARTUP and the last 2 with .EXIT, just to make him happy   :P
_main   PROC

        .STARTUP

        MOV     AL,5
        ADD     AL,X

        .EXIT

_main   ENDP


the program doesn't appear to do much when you run it
but, it does return an exit code of 8 (5+X), that could be accessed in a batch file with ERRORLEVEL commands

MichaelW

I think DGROUP and various other details of the segment structure were required if "programs compiled by Microsoft translators are to run properly" (quote from The MS-DOS Encyclopedia, Microsoft Press, 1988). The DS=SS allows you to change the value of DS without having to preserve the old value, and in a program with an interrupt handler readily access the program's near data from the handler.
Well Microsoft, here's another nice mess you've gotten us into.

dedndave

yah - that directive may also alter the SS segment ASSUME
that wouldn't be evident in the disassembled code, but they probably reference DGROUP

sb1370

Thanks for your answers.

I use Visual Studio 2012 as IDE with this trick:
http://www.codeproject.com/Articles/271627/Assembly-Programming-with-Visual-Studio-2010-2012

I tried the teacher code and it returned these errors;
error A2074: cannot access label through segment registers
error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\test.obj" /W3 /errorReport:prompt  /Tatest.ASM" exited with code 1.

And I tried your code which returned these errors:
error A2006: undefined symbol : DGROUP
error A2074: cannot access label through segment registers
error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\test.obj" /W3 /errorReport:prompt  /Tatest.ASM" exited with code 1.

I tried this code.
.MODEL SMALL
.DATA
.CODE
main:
MOV AX,5
ADD AX,5
end main
.EXIT
END

It assembles but while debugging this message is shown:
ASM1.exe has triggered a breakpoint.

I tried teacher's code on emu 8086 and it executed without any problem. I think emu8086 uses FASM assembler.


jj2007

Quote from: sb1370 on April 28, 2013, 11:44:42 PM
And I tried your code which returned these errors:
error A2006: undefined symbol : DGROUP
error A2074: cannot access label through segment registers

Try again with /omf in the assembler's commandline (it works, just tested).

MichaelW

Quote from: sb1370 on April 28, 2013, 11:44:42 PM
I use Visual Studio 2012 as IDE with this trick:
http://www.codeproject.com/Articles/271627/Assembly-Programming-with-Visual-Studio-2010-2012

The article makes no mention of 16-bit code.

If I take the first source that you posted and assemble it, using ML 6.15, with:

ML /W3 /c test.asm

And link, using the 16-bit linker from the MASM32 distribution, with:

Link16 test;

Then the only problem is a no stack segment warning from the linker, which in this case can be safely ignored, or can be eliminated by adding a .STACK directive to the source.

If I take the same source and try to assemble it with a very normal command line for 32-bit code:

ML /W3 /c /coff test.asm

Then I get:

test.asm(6) : error A2006: undefined symbol : DGROUP
test.asm(8) : error A2074: cannot access label through segment registers


Your problems here have a solution that should be obvious. To edit the source you can use any workable editor, notepad is handy, and to compile and link you can use a batch file.

And if your program needs to access its data you are going to need to set a segment register so it points to the data segment, and if you expect to do the access without a segment override the segment register needs to be DS. The .STARTUP directive provides an easy way to do this, and it also establishes the program entry point as the location of the directive. And while there are multiple ways of terminating the program, the .EXIT directive provides an easy way to do it correctly.
Well Microsoft, here's another nice mess you've gotten us into.

jj2007

It appears that the OP is using a higher version of ML.exe, therefore my suggestion to add /omf.

sb1370

I tried /omf option. Now I get this error:
error LNK1107: invalid or corrupt file: cannot read at 0x1CF

dedndave

first, try and build it without the debug switches
i am not sure how useful those symbols will be for a 16-bit file, anyways
also, be sure you are using LINK16.EXE, not LINK.EXE

ml /c /omf Tatest.asm
link16 Tatest.obj;


notice the semicolon at the end of the link16 line

i get the following warning from masm
Quotestart address ignored with .STARTUP
that's ok - the OBJ is still created

i get the following warning from link
Quotewarning - no stack segment
it seems to build the EXE, anyways

let's correct those warnings
        .MODEL  SMALL
        .STACK
        .386

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

        .DATA

X       DB 3

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

        .CODE

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

_main   PROC

        .STARTUP

        MOV     AL,5
        ADD     AL,X

        .EXIT

_main   ENDP

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

        END


now, it builds without any problems using the above command lines

sb1370

Sorry for coming back late.
Thanks for your answers. I read your solution weeks ago but I was busy with my exams.
By the way with your solution I have two problems:
I can't set visual studio to use linker16. I downloaded MASM and extracted, renamed linker16 to linker copied  it to visual studio folder, but linker16 need ';'. I couldn't set visual studio to use ';' after filename.
Also I use Windows 8 x64 edition so I can't run 16bit program natively .
What change I should do to make my codes to be compiled in 32bit?

dedndave

your teacher is going to have to keep up with the times - lol
there are probably many students that are using 64-bit OS's

this should assemble, provided you have installed the masm32 package
;###############################################################################################

        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .List

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

;        .DATA

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

;        .DATA?

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

        .CODE

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

_main   PROC

        mov     eax,5
        add     eax,5
        print   str$(eax),13,10
        inkey
        INVOKE  ExitProcess,0

_main   ENDP

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

        END     _main

MichaelW

To be clear, the 16-bit linker is not a 16-bit program. Terminating the link16 command line with a semicolon tells it to use the defaults for the remainder of the fields, instead of prompting you for the names.

The command line syntax is:

LINK16 <objs>,<exefile>,<mapfile>,<libs>,<deffile>

You can do without the semicolon and avoid the prompts by specifying all of the required fields. So for example to link test.obj and create test.exe and test.map, without specifying a LIB or DEF file, you could use:

LINK16 test, test, test, nul, nul

And the linker would add the appropriate extensions and ignore the libs and deffile fields. And other syntaxes are possible, for example:

LINK16 test, test, test,,,
Well Microsoft, here's another nice mess you've gotten us into.