News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Unmatched block nesting

Started by carlottagp, August 10, 2006, 08:49:49 PM

Previous topic - Next topic

carlottagp

My program has the following basic structure:

TITLE       LDA
.MODEL          SMALL
.STACK      200h
.DATA

(data)

.CODE

mov   AX,@DATA
mov   DS,AX

LDAB   PROC

(code)

Five procedures, each with the xxx PROC,  RET, xxx  ENDP format

ZE:   mov   AX,4C00h
     int   21h

LDAB   ENDP
      END

When I try to assemble it, I get the error message:

LDA.asm (259)   Fatal error A1010: unmatched block nesting: LDAB

All of the procedures function correctly on their own, and in any case that's
apparently not where my problem is.  Can someone explain the "unmatched
block nesting" comment to me?  Thanks

Michael









Mark Jones

Hi Michael, you have one PROC inside another PROC? I could be mistaken but I don't think that is allowed. :)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

carlottagp

Mark,

Thanks for the suggestion.  Actually, I have about eight programs written so far, all of
which have procedures inside the main procedure, and they all work just fine.  In other
words, in the main program I have a number of CALL instructions, each of which invokes
a subroutine with the format I mentioned:  PROC......code.....RET..ENDP.

For instance (the smallest subroutine I've written so far)

CRLF   PROC             ;writes CR, LF to file
   mov   AH,40h      
   mov   BX,handle
   mov   CX,2
   mov   DX,offset buffc
   int   21h
   jc   MB
   RET
CRLF   ENDP


Mark Jones

Hmm, it sounds like the error message is generated if another PROC is encountered before the previous ENDP, i.e.


MyProc1 PROC
    mov ax,1
MyProc2 PROC
    mov cx,2
    ret
ENDP          ; two procs, which ENDP to use?
    ret 8
ENDP          ; hmmm


Could you try altering the code as follows?


MyProc1:
    mov ax,1
MyProc2:
    mov cx,2
    ret


The procedure label defined by the PROC command should in interchangable with a jump label (they are both converted to an offset at compile-time.) I hope this is what you are after, have fun! :U
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

carlottagp

Hello again,

All of my procedures are in the same format as the example I posted; i.e. no CALLs to another
procedure within the one that's running.  I have tried moving all procedures to a point
after the ENDP  END for the main procedure, with no success. Is it possible that there's
a number-of-lines limit problem here?

Not trying to muddy the waters, but could there be a problem with the software I'm
using to assemble my programs?  It came with Kip Irvine's assembly language book.  This
morning I observed, using the CodeView 4.10 that came with it, that a line was skipped
as I was stepping through the program, trying to debug it.  Just an ordinary line, something
like   mov BX, 12h.  It happened again and again. I'm bothered enough to want to go out
and try to find a package of assembly language software....

Thanks again,

Michael

MichaelW

I doubt that the problem has anything to do with line length or the tools. The only way I can find to produce an unmatched block nesting error with code like you seem to be describing is to have an overlap between the procedure definitions, as in Mark's example. IIRC you cannot nest procedures that have a stack frame, and without a stack frame a procedure cannot support parameters or local variables, so under these conditions a procedure is little better than label, so why not just use a label?

eschew obfuscation

carlottagp

Hi, Michael,

I am interested in your suggestion to use a label instead of a procedure.  ......except that I don't see how
to implement the return function at the end of the procedure.  Could you perhaps illustrate the idea by
showing me how to write the CRLF subroutine I quoted earlier?  At the moment I just CALL the procedure
when I need to, and this puts the appropriate return address on the stack, to be used when the RET
instruction is encountered.

Incidentally, by shuffling the order in which the subroutines are called I was able to make the original
program work.  However, CodeView insists that there is a "fatal error" in the program; this is why I wonder
if my assembly-language software, including CV, is flaky...

Thanks,

Michael

ChrisLeslie

carlottagp

Your original code should have an "end xxx" directive with an entry label instead of just "end".
You can call or invoke proc from within procs, but if you nest a proc within a proc, the ret instruction will return program flow to the wrong place.
As MichaelW said, it may be appropriate to use simple labels instead of procs in many circumstances if you are not using a stack frame. In this way you will effectively be creating subroutines. For example, the CRLF subroutine could be:
CRLF:
  .data
  labcrlf db 13,10,'$'
  .code
  mov ah,9
  mov dx,offset labcrlf
  int 21h
  ret

where you use "call CRLF".
Or better still in my opinoin is a macro:

CRLF MACRO
  local labcrlf
.data
  labcrlf db 13,10,'$'
  .code
  mov ah,9
  mov dx,offset labcrlf
  int 21h
ENDM

where you just use CRLF in your code.

Regards

Chris

sinsi

ML will let you have nested PROCs:

proc1 proc
mov eax,eax
proc2 proc
  ret
proc2 endp
ret
proc1 endp

main proc
call proc1
call proc2
ret
main endp

will compile and link no worries.

With your CRLF proc,
Quote
CRLF   PROC             ;writes CR, LF to file
   mov   AH,40h     
   mov   BX,handle
   mov   CX,2
   mov   DX,offset buffc
   int   21h
   jc   MB
   RET
CRLF   ENDP
jumping out of a PROC is as bad as a BASIC GOTO (a PROC is self-contained
and has one exit point (so I have been told  :lol))

ChrisLeslie: using your macro 50 times in a program will scatter 50 times "13,10,$"
through your .data  :eek
Light travels faster than sound, that's why some people seem bright until you hear them.

ChrisLeslie

sinsi,

The problem with the nested proc example that you gave is that any code that may exist in proc1 after the proc2 block will not be executed because proc2's "ret" will cause proc1 to return.

Unfortunately that is correct that when using macros that code, and any data, is repeated upon every invocation. I think it depends on the circumstances and one's preferences whether a macro is the best choice.

Regards

Chris

sinsi

Sorry Chris, bad example since proc2 doesn't need to return if proc1 does.
(Too lazy to actually think up some code that works heh heh.)

On that CRLF macro, maybe something like

CRLF MACRO
  IFNDEF str_crlf
    .data
    str_crlf db 13,10,'$'
  ENDIF
  .code
  mov ah,9
  mov dx,offset str_crlf
  int 21h
ENDM

would only define it once?
Light travels faster than sound, that's why some people seem bright until you hear them.

ChrisLeslie

Ahh, IFENDEF. That should be an improvement. I havn't used it yet but it sounds useful.

Chris

MichaelW

Quote from: sinsi on August 17, 2006, 05:36:43 AM
ML will let you have nested PROCs

Yes, but only if the procedures do not have parameters or automatic local variables. If they do, then you will get:

error A2144: cannot nest procedures
eschew obfuscation

sinsi

Oops :red. We live and learn. In my meagre defense, I have never used nested PROCs in ASM (I think Delphi treats one as a "local" procedure?).

MichaelW, I am curious as to what an "automatic local variable" is. I understand a defined local variable but what's an automatic one?
Light travels faster than sound, that's why some people seem bright until you hear them.

MichaelW

By automatic local variable I mean a local variable created with the LOCAL directive. MASM will not return an error if a nested procedure has local variables that were created manually. And my statement was not correct. For a nested procedure with LOCAL and no parameters, MASM returns:

error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
eschew obfuscation