MASM32 error while assembling / begin: / end begin

Started by Earnie, July 15, 2010, 06:42:38 PM

Previous topic - Next topic

Earnie

Hi,

I've started to work through the book "Writing DOS Device Drivers" and I got stuck at assembling the SimpleDriver.asm
If you don't know the book, the whole code is below.

I've searched the forum but I didn't find anything.
Although I find it hard to believe that such a thread doesn't exist somewhere here.
This is the code (it's supposed to only make a beep sound)

;************************************************************
;*   This is a simple Device Driver                         *
;************************************************************


;************************************************************
;*   INSTRUCTING THE ASSEMBLER                              *
;************************************************************

cseg      segment   para       public  'code'     
simple    proc      far                 
          assume    cs:cseg,es:cseg,ds:cseg

;************************************************************
;*   MAIN PROCEDURE CODE                                    *
;************************************************************

begin:

;************************************************************
;*   DEVICE HEADER REQUIRED BY DOS                          *
;************************************************************

next_dev      dd     -1             
attribute     dw     2000h           
strategy      dw     dev_strategy
interrupt     dw     dev_int
dev_name      db     'SIMPLE$ '

;************************************************************
;*   WORK SPACE FOR OUR DEVICE DRIVER                       *
;************************************************************

rh_off        dw    ?
rh_seg        dw    ?
msgl          db    07h
              db    'The Waite Group Simple Device Driver! '
              db    0dh,0ah,07h,'$'
   
;************************************************************
;*   THE STRATEGY PROCEDURE                                 *
;************************************************************

dev_strategy:
        mov    cs:rh_seg,es
        mov    cs:rh_off,bx
        ret 

;************************************************************
;*   THE INTERRUPT PROCEDURE                                *
;************************************************************

dev_int:
        cld   
        push  ds
        push  es
        push  ax
        push  bx
        push  cx
        push  dx
        push  di
        push  si

        mov   al,es:[bx]+2
        cmp   al,0
        jnz   exit3
        rol   al,1
        lea   di,cmdtab
        mov   ah,0
        add   di,ax
        jmp   word ptr[di]

cmdtab  label   byte
        dw      init 

;************************************************************
;*   YOUR LOCAL PROCEDURES                                  *
;************************************************************

initial  proc   near
         lea    dx,msgl
         mov    ah,9
         int    21h
         ret
initial  endp
       

;************************************************************
;*   DOS COMMAND PROCESSING                                 *
;************************************************************

init:   call   initial
        jmp    exit2

;************************************************************
;*   ERROR EXIT                                             *
;************************************************************

exit3:  mov    es:word ptr 3[bx],8103h
        jmp    exit1

;************************************************************
;*   COMMON EXIT                                            *
;************************************************************

exit2:
        mov    es:word ptr 3[bx],0100h
exit1:  mov    bx,cs:rh_off
        mov    es,cs:rh_seg
exit0:  pop    si
        pop    di
        pop    dx
        pop    cx
        pop    bx
        pop    ax
        pop    es
        pop    ds
        ret

;************************************************************
;*   END OF PROGRAM                                         *
;************************************************************

simple  endp
cseg    ends
        end    begin 

; program end


MASM32 gave the following errors:

error A2006: undefined symbol : begin
error A2148: invalid symbol type in expression : begin

It's not a spelling error, so what is it?

Thanks in advance,

Earnie

clive

You need to get rid of the "simple proc/simple endp" pair as they will make the "begin" symbol local to the PROCedure, either that or make begin public.

The code was designed for MASM 5.1, you can assemble it with MASM 6.xx by using the /Zm command line option.
ie ML /Zm simple.asm
It could be a random act of randomness. Those happen a lot as well.


clive

Quote from: Earnie on July 15, 2010, 07:28:32 PM
How do I make it public?

Use "begin equ $" instead of "begin:", or Use MASM 5.1 or Use MASM 6.xx with /Zm or get rid of the PROC/ENDP pair.
It could be a random act of randomness. Those happen a lot as well.

Earnie

A) Getting rid of the pair

    That caused an additional "error A2008: syntax error : begin" at the location where I mentioned begin the first time.


B) begin equ $

   Caused only  one error: "error A2148: invalid symbol type in expression : begin" at the location where I mentioned begin the second time.

   I just wrote "begin equ $" instead of "begin :"


Thanks for the help so far, but what now? :-( Is there a chance without installing another version?

BTW, I'm using the MASM32 SDK from masm32.com and I'm assembling in the program qeditor.exe

qWord

FPU in a trice: SmplMath
It's that simple!

clive

Quote from: Earnie on July 15, 2010, 08:02:28 PM
A) Getting rid of the pair

    That caused an additional "error A2008: syntax error : begin" at the location where I mentioned begin the first time.

Ok, well no errors here with MASM 6.14

ml  -Fl  -c  test31.asm

TEST31.ASM
;************************************************************
;*   This is a simple Device Driver                         *
;************************************************************


;************************************************************
;*   INSTRUCTING THE ASSEMBLER                              *
;************************************************************

cseg      segment   para       public  'code'
          assume    cs:cseg,es:cseg,ds:cseg

;************************************************************
;*   MAIN PROCEDURE CODE                                    *
;************************************************************

begin:

;************************************************************
;*   DEVICE HEADER REQUIRED BY DOS                          *
;************************************************************

next_dev      dd     -1
attribute     dw     2000h
strategy      dw     dev_strategy
interrupt     dw     dev_int
dev_name      db     'SIMPLE$ '

;************************************************************
;*   WORK SPACE FOR OUR DEVICE DRIVER                       *
;************************************************************

rh_off        dw    ?
rh_seg        dw    ?
msgl          db    07h
              db    'The Waite Group Simple Device Driver! '
              db    0dh,0ah,07h,'$'

;************************************************************
;*   THE STRATEGY PROCEDURE                                 *
;************************************************************

dev_strategy:
        mov    cs:rh_seg,es
        mov    cs:rh_off,bx
        ret

;************************************************************
;*   THE INTERRUPT PROCEDURE                                *
;************************************************************

dev_int:
        cld
        push  ds
        push  es
        push  ax
        push  bx
        push  cx
        push  dx
        push  di
        push  si

        mov   al,es:[bx]+2
        cmp   al,0
        jnz   exit3
        rol   al,1
        lea   di,cmdtab
        mov   ah,0
        add   di,ax
        jmp   word ptr[di]

cmdtab  label   byte
        dw      init

;************************************************************
;*   YOUR LOCAL PROCEDURES                                  *
;************************************************************

initial  proc   near
         lea    dx,msgl
         mov    ah,9
         int    21h
         ret
initial  endp


;************************************************************
;*   DOS COMMAND PROCESSING                                 *
;************************************************************

initx equ $

init:   call   initial
        jmp    exit2

;************************************************************
;*   ERROR EXIT                                             *
;************************************************************

exit3:  mov    es:word ptr 3[bx],8103h
        jmp    exit1

;************************************************************
;*   COMMON EXIT                                            *
;************************************************************

exit2:
        mov    es:word ptr 3[bx],0100h
exit1:  mov    bx,cs:rh_off
        mov    es,cs:rh_seg
exit0:  pop    si
        pop    di
        pop    dx
        pop    cx
        pop    bx
        pop    ax
        pop    es
        pop    ds
        ret

;************************************************************
;*   END OF PROGRAM                                         *
;************************************************************

cseg    ends
        end    begin

; program end


TEST31.LST
Microsoft (R) Macro Assembler Version 6.14.8444     07/15/10 15:17:49
test31.asm      Page 1 - 1


;************************************************************
;*   This is a simple Device Driver                         *
;************************************************************


;************************************************************
;*   INSTRUCTING THE ASSEMBLER                              *
;************************************************************

0000 cseg      segment   para       public  'code'
          assume    cs:cseg,es:cseg,ds:cseg

;************************************************************
;*   MAIN PROCEDURE CODE                                    *
;************************************************************

0000 begin:

;************************************************************
;*   DEVICE HEADER REQUIRED BY DOS                          *
;************************************************************

0000 FFFFFFFF next_dev      dd     -1
0004 2000 attribute     dw     2000h
0006 0041 R strategy      dw     dev_strategy
0008 004C R interrupt     dw     dev_int
000A 53 49 4D 50 4C 45 dev_name      db     'SIMPLE$ '
       24 20

;************************************************************
;*   WORK SPACE FOR OUR DEVICE DRIVER                       *
;************************************************************

0012 0000 rh_off        dw    ?
0014 0000 rh_seg        dw    ?
0016 07 msgl          db    07h
0017  54 68 65 20 57 61               db    'The Waite Group Simple Device Driver! '
       69 74 65 20 47 72
       6F 75 70 20 53 69
       6D 70 6C 65 20 44
       65 76 69 63 65 20
       44 72 69 76 65 72
       21 20
003D  0D 0A 07 24               db    0dh,0ah,07h,'$'

;************************************************************
;*   THE STRATEGY PROCEDURE                                 *
;************************************************************

0041 dev_strategy:
0041  2E: 8C 06 0014 R         mov    cs:rh_seg,es
0046  2E: 89 1E 0012 R         mov    cs:rh_off,bx
004B  C3         ret

;************************************************************
;*   THE INTERRUPT PROCEDURE                                *
;************************************************************

004C dev_int:
004C  FC         cld
004D  1E         push  ds
004E  06         push  es
004F  50         push  ax
0050  53         push  bx
0051  51         push  cx
0052  52         push  dx
0053  57         push  di
0054  56         push  si

0055  26: 8A 47 02         mov   al,es:[bx]+2
0059  3C 00         cmp   al,0
005B  75 1C         jnz   exit3
005D  D0 C0         rol   al,1
005F  8D 3E 0069 R         lea   di,cmdtab
0063  B4 00         mov   ah,0
0065  03 F8         add   di,ax
0067  FF 25         jmp   word ptr[di]

0069 cmdtab  label   byte
0069  0074 R         dw      init

;************************************************************
;*   YOUR LOCAL PROCEDURES                                  *
;************************************************************

006B initial  proc   near
006B  8D 16 0016 R          lea    dx,msgl
006F  B4 09          mov    ah,9
0071  CD 21          int    21h
0073  C3          ret
0074 initial  endp


;************************************************************
;*   DOS COMMAND PROCESSING                                 *
;************************************************************

0074 = 0074 initx equ $

0074  E8 FFF4 init:   call   initial
0077  EB 08         jmp    exit2

;************************************************************
;*   ERROR EXIT                                             *
;************************************************************

0079  26: C7 47 03 8103 exit3:  mov    es:word ptr 3[bx],8103h
007F  EB 06         jmp    exit1

;************************************************************
;*   COMMON EXIT                                            *
;************************************************************

0081 exit2:
0081  26: C7 47 03 0100         mov    es:word ptr 3[bx],0100h
0087  2E: 8B 1E 0012 R exit1:  mov    bx,cs:rh_off
008C  2E: 8E 06 0014 R         mov    es,cs:rh_seg
0091  5E exit0:  pop    si
0092  5F         pop    di
0093  5A         pop    dx
0094  59         pop    cx
0095  5B         pop    bx
0096  58         pop    ax
0097  07         pop    es
0098  1F         pop    ds
0099  C3         ret

;************************************************************
;*   END OF PROGRAM                                         *
;************************************************************

009A cseg    ends
        end    begin

; program end
It could be a random act of randomness. Those happen a lot as well.

clive

Quote from: Earnie
B) begin equ $

   Caused only  one error: "error A2148: invalid symbol type in expression : begin" at the location where I mentioned begin the second time.

   I just wrote "begin equ $" instead of "begin :"

ml  -Fl  -c test33.asm

TEST33.ASM
;************************************************************
;*   This is a simple Device Driver                         *
;************************************************************


;************************************************************
;*   INSTRUCTING THE ASSEMBLER                              *
;************************************************************

cseg      segment   para       public  'code'
simple    proc      far
          assume    cs:cseg,es:cseg,ds:cseg

;************************************************************
;*   MAIN PROCEDURE CODE                                    *
;************************************************************

begin   equ     $

;************************************************************
;*   DEVICE HEADER REQUIRED BY DOS                          *
;************************************************************

next_dev      dd     -1
attribute     dw     2000h
strategy      dw     dev_strategy
interrupt     dw     dev_int
dev_name      db     'SIMPLE$ '

;************************************************************
;*   WORK SPACE FOR OUR DEVICE DRIVER                       *
;************************************************************

rh_off        dw    ?
rh_seg        dw    ?
msgl          db    07h
              db    'The Waite Group Simple Device Driver! '
              db    0dh,0ah,07h,'$'

;************************************************************
;*   THE STRATEGY PROCEDURE                                 *
;************************************************************

dev_strategy:
        mov    cs:rh_seg,es
        mov    cs:rh_off,bx
        ret

;************************************************************
;*   THE INTERRUPT PROCEDURE                                *
;************************************************************

dev_int:
        cld
        push  ds
        push  es
        push  ax
        push  bx
        push  cx
        push  dx
        push  di
        push  si

        mov   al,es:[bx]+2
        cmp   al,0
        jnz   exit3
        rol   al,1
        lea   di,cmdtab
        mov   ah,0
        add   di,ax
        jmp   word ptr[di]

cmdtab  label   byte
        dw      init

;************************************************************
;*   YOUR LOCAL PROCEDURES                                  *
;************************************************************

initial  proc   near
         lea    dx,msgl
         mov    ah,9
         int    21h
         ret
initial  endp


;************************************************************
;*   DOS COMMAND PROCESSING                                 *
;************************************************************

init:   call   initial
        jmp    exit2

;************************************************************
;*   ERROR EXIT                                             *
;************************************************************

exit3:  mov    es:word ptr 3[bx],8103h
        jmp    exit1

;************************************************************
;*   COMMON EXIT                                            *
;************************************************************

exit2:
        mov    es:word ptr 3[bx],0100h
exit1:  mov    bx,cs:rh_off
        mov    es,cs:rh_seg
exit0:  pop    si
        pop    di
        pop    dx
        pop    cx
        pop    bx
        pop    ax
        pop    es
        pop    ds
        ret

;************************************************************
;*   END OF PROGRAM                                         *
;************************************************************

simple  endp
cseg    ends
        end    begin

; program end


TEST33.LST
Microsoft (R) Macro Assembler Version 6.14.8444     07/15/10 15:21:27
test33.asm      Page 1 - 1


;************************************************************
;*   This is a simple Device Driver                         *
;************************************************************


;************************************************************
;*   INSTRUCTING THE ASSEMBLER                              *
;************************************************************

0000 cseg      segment   para       public  'code'
0000 simple    proc      far
          assume    cs:cseg,es:cseg,ds:cseg

;************************************************************
;*   MAIN PROCEDURE CODE                                    *
;************************************************************

0000 = 0000 begin   equ     $

;************************************************************
;*   DEVICE HEADER REQUIRED BY DOS                          *
;************************************************************

0000 FFFFFFFF next_dev      dd     -1
0004 2000 attribute     dw     2000h
0006 0041 R strategy      dw     dev_strategy
0008 004C R interrupt     dw     dev_int
000A 53 49 4D 50 4C 45 dev_name      db     'SIMPLE$ '
       24 20

;************************************************************
;*   WORK SPACE FOR OUR DEVICE DRIVER                       *
;************************************************************

0012 0000 rh_off        dw    ?
0014 0000 rh_seg        dw    ?
0016 07 msgl          db    07h
0017  54 68 65 20 57 61               db    'The Waite Group Simple Device Driver! '
       69 74 65 20 47 72
       6F 75 70 20 53 69
       6D 70 6C 65 20 44
       65 76 69 63 65 20
       44 72 69 76 65 72
       21 20
003D  0D 0A 07 24               db    0dh,0ah,07h,'$'

;************************************************************
;*   THE STRATEGY PROCEDURE                                 *
;************************************************************

0041 dev_strategy:
0041  2E: 8C 06 0014 R         mov    cs:rh_seg,es
0046  2E: 89 1E 0012 R         mov    cs:rh_off,bx
004B  CB         ret

;************************************************************
;*   THE INTERRUPT PROCEDURE                                *
;************************************************************

004C dev_int:
004C  FC         cld
004D  1E         push  ds
004E  06         push  es
004F  50         push  ax
0050  53         push  bx
0051  51         push  cx
0052  52         push  dx
0053  57         push  di
0054  56         push  si

0055  26: 8A 47 02         mov   al,es:[bx]+2
0059  3C 00         cmp   al,0
005B  75 1C         jnz   exit3
005D  D0 C0         rol   al,1
005F  8D 3E 0069 R         lea   di,cmdtab
0063  B4 00         mov   ah,0
0065  03 F8         add   di,ax
0067  FF 25         jmp   word ptr[di]

0069 cmdtab  label   byte
0069  0074 R         dw      init

;************************************************************
;*   YOUR LOCAL PROCEDURES                                  *
;************************************************************

006B initial  proc   near
006B  8D 16 0016 R          lea    dx,msgl
006F  B4 09          mov    ah,9
0071  CD 21          int    21h
0073  C3          ret
0074 initial  endp


;************************************************************
;*   DOS COMMAND PROCESSING                                 *
;************************************************************

0074  E8 FFF4 init:   call   initial
0077  EB 08         jmp    exit2

;************************************************************
;*   ERROR EXIT                                             *
;************************************************************

0079  26: C7 47 03 8103 exit3:  mov    es:word ptr 3[bx],8103h
007F  EB 06         jmp    exit1

;************************************************************
;*   COMMON EXIT                                            *
;************************************************************

0081 exit2:
0081  26: C7 47 03 0100         mov    es:word ptr 3[bx],0100h
0087  2E: 8B 1E 0012 R exit1:  mov    bx,cs:rh_off
008C  2E: 8E 06 0014 R         mov    es,cs:rh_seg
0091  5E exit0:  pop    si
0092  5F         pop    di
0093  5A         pop    dx
0094  59         pop    cx
0095  5B         pop    bx
0096  58         pop    ax
0097  07         pop    es
0098  1F         pop    ds
0099  CB         ret

;************************************************************
;*   END OF PROGRAM                                         *
;************************************************************

009A simple  endp
009A cseg    ends
        end    begin

; program end
It could be a random act of randomness. Those happen a lot as well.

dedndave

it has been a while since i wrote one of these, but one thing i do remember...
the strategy and interrupt routines are typed FAR
that means the RET instructions need to be RETF's
you can either specify RETF, or make the PROC's FAR...
dev_strategy PROC FAR
        mov    cs:rh_seg,es
        mov    cs:rh_off,bx
        ret
dev_strategy ENDP

the assembler places a RETF automatically if it is a FAR PROC
all the RET's for the interrupt routine need to be FAR, as well

EDIT - also - i am not sure that a device attribute of 2000h is valid - as i said - it's been a while - lol
i think that makes it a block device
as i recall, if bit 15 is set, it is a character device

someplace, i have written a ram-disk and an ansi.sys driver - let me see if i can find them

clive

Quote from: Earnie
or the help so far, but what now? :-( Is there a chance without installing another version?

BTW, I'm using the MASM32 SDK from masm32.com and I'm assembling in the program qeditor.exe

Be aware that you are attempting 16-DOS device drivers, which most of us haven't had to spend time on for 15 years.

MASM32 is a 32-bit package, and MASM 6.14 expects to be building 32-bit apps, linking with a 32-bit linker.

You will need to use the ML -c option to force it to compile(assemble) only, and use the 16-bit linker (LINK16.EXE in \MASM32\BIN).

Microsoft (R) Segmented Executable Linker  Version 5.60.339 Dec  5 1994
Copyright (C) Microsoft Corp 1984-1993.  All rights reserved.

Usage:

LINK
LINK @<response file>
LINK <objs>,<exefile>,<mapfile>,<libs>,<deffile>

Valid options are:
 /?                             /ALIGNMENT
 /BATCH                         /CODEVIEW
 /CPARMAXALLOC                  /DOSSEG
 /DSALLOCATE                    /DYNAMIC
 /EXEPACK                       /FARCALLTRANSLATION
 /HELP                          /HIGH
 /INFORMATION                   /LINENUMBERS
 /MAP                           /NODEFAULTLIBRARYSEARCH
 /NOEXTDICTIONARY               /NOFARCALLTRANSLATION
 /NOGROUPASSOCIATION            /NOIGNORECASE
 /NOLOGO                        /NONULLSDOSSEG
 /NOPACKCODE                    /NOPACKFUNCTIONS
 /NOFREEMEM                     /OLDOVERLAY
 /ONERROR                       /OVERLAYINTERRUPT
 /PACKCODE                      /PACKDATA
 /PACKFUNCTIONS                 /PAUSE
 /PCODE                         /PMTYPE
 /QUICKLIBRARY                  /SEGMENTS
 /STACK                         /TINY
 /WARNFIXUP
It could be a random act of randomness. Those happen a lot as well.

Earnie

I'm gonna look at all this tomorrow (or the day after that, tomorrow is a busy day).

It's sleeping time for me now.

I'll be back.

See ya

clive

Quote from: dedndave
the assembler places a RETF automatically if it is a FAR PROC
all the RET's for the interrupt routine need to be FAR, as well

EDIT - also - i am not sure that a device attribute of 2000h is valid - as i said - it's been a while - lol
i think that makes it a block device
as i recall, if bit 15 is set, it is a character device

Indeed, not sure this is a very good example of a driver, the "MS-DOS Programmer's Reference" might be a better source, or the "Advanced MS-DOS Programming: The Microsoft Guide for Assembly Language and C Programmers"

Most of mine were orders of magnitude more complex, with all the procedures defined independently/explicitly. And while MS-DOS (newer versions) will load .SYS files that are .EXE (MZ) files internally, they probably should be zero based (/TINY ?) because they were relatively flat (lacking multiple segments) as you typically put discardable initialization code at the back of the driver and truncate the size down. As I recalled I used MASM 5.x or TASM to build them.
It could be a random act of randomness. Those happen a lot as well.

dedndave

here ya go - old-time stuff   :P

one of each - a character device and a block device

i take no responsibility for appearance - lol

Earnie

I put the original SimpleDriver.asm in the masm32\bin\ folder and tried

ml  -Fl  -c  SimpleDriver.asm

Again, error A2008 and error A2006.



I then assembled the modified version


begin = $
...
end OFFSET begin


with the same command and it worked. I'm not sure though what "begin = $"  actually does.

dedndave

as the assembler generates code, it increments the "program counter" to keep track of the address
in masm, "$" inserts the current program counter value
begin = $
sets the value of the label "begin" to the current program counter address

"=" is similar to "EQU", except that values assigned with "=" may be re-assigned (altered)
values assigned using "EQU" are permanent and may not be re-assigned
it's also less typing   :lol

in your code, "OFFSET begin" and "begin" should return the same thing

we usually use a code branch label for the END directive
code branch labels are similar....

start:

;some code here

end start