[comp.sys.ibm.pc] MASM 5.1 help needed

gregory@cbnewsd.ATT.COM (gregory.a.youngdahl) (09/20/89)

Hi,
	Can someone more familiar with assembly language (and in particular
MASM 5.1) help me with a problem?

THE PROBLEM:
	While trying to port some code to MASM 5.1 (that assembled under
an earlier release of MASM, probably a 4.x version) I am encountering one
of the dreaded PHASE ERRORS.  The documentation explains how jump or call
instructions can have a phase error, and I can understand why and what to
attack to try to fix them.  However this particular error concerns a MOV
instruction and the documents have no information about this problem.  I
have been able to reduce the problem code to an 11 line program that
produces the identical error (although it looks pretty useless).  Please
note that this is a problem getting the code through the assembler, rather
than an execution time error.

SOME CONTEXT:
	What the code is trying to do is install the interrupt vector
for it's interrupt routines using service 25H of INT 21H (both routines
exhibit the same problem).  This requires loading the offset of the
interrupt routine into the DX register, and the segment into the DS
register.  However, the DS register (apparently) can only be loaded
through another register so the segment value is loaded into CX and
transferred into DS.  The PHASE ERROR occurs with the instruction
to load the CX register with the segment value.

	The gory details follow - hit 'n' now or else :-)

MY ANALYSIS:
	I have included TRYIT.ASM, an 11 line program that exhibits the
same error, as well as the pass 1 and pass 2 listing files output by the
assembler.  The pass 1 listing indicates an undefined symbol (myint) when
it encounters the MOV instruction.  This is expected since myint is a
forward reference.  It codes a B9 for the MOV and ---- to indicate that
the linker will need to resolve the segment value, and marks the value
as U (for undefined I guess).  This also makes sense.  Then there is
this mysterious 90 after the U.  Counting bytes indicates that this
is counted as part of the code.  Interpreting this as an opcode would be
an XCHG of the accumulator with itself, effectively a NOP.  However,
by pass 2 myint is defined (although its segment value can't be
determined of course), and the 90 disappears, all further code moves
up a byte, and voila - PHASE ERRORS!
	So the question is: what is going on here, and how can I
conquer it?  I assume the 90 is an attempt to reserve some additional
space (in case a segment value suddenly requires 3 bytes???? :-).  If
they would leave it there I suppose it wouldn't be too bad (unless
performance or code space was critical), but they don't, and I don't
see what I can do about it.  I spent a fruitless 35 minute long distance
phone call with Microsoft technical support.  The final resolution was
if I could create a 10 (or less) line program that exhibited the error
and read it to them over the phone perhaps they could get to the problem,
but they had no interest in my 500+ line program (I can understand that).
I can probably reduce my 11 lines down to 9 by eliminating the RET
instructions.  I thought I would try the net before wasting any more
long distance $$$.  Any help will be greatly appreciated.

Thanks,
Greg Youngdahl    AT&T Bell Laboratories   Naperville IL
att!iwsgw!greg


===================================================================

The TRYIT.ASM file:

_TEXT	SEGMENT BYTE PUBLIC 'CODE'
	ASSUME	CS: _TEXT
install	proc	near
	mov	cx,seg myint
	ret
install	endp
myint	proc	far
	ret
myint endp
_TEXT	ENDS
	END

===================================================================

PASS 1 listing:

 0000				_TEXT	SEGMENT BYTE PUBLIC 'CODE'
					ASSUME	CS: _TEXT
 0000				install	proc	near
 0000  B9 ---- U 90			mov	cx,seg myint
tryit.asm(4): error A2009: Symbol not defined: MYINT
 0004  C3				ret
 0005				install	endp
 0005				myint	proc	far
 0005  CB				ret
 0006				myint endp
 0006				_TEXT	ENDS
					END

PASS 2 listing:

 0000				_TEXT	SEGMENT BYTE PUBLIC 'CODE'
					ASSUME	CS: _TEXT
 0000				install	proc	near
 0000  B9 ---- R			mov	cx,seg myint
 0003  C3				ret
 0004				install	endp
tryit.asm(6): error A2006: Phase error between passes
				myint	proc	far
tryit.asm(7): error A2006: Phase error between passes
 0005  CB				ret
 0006				myint endp
 0006				_TEXT	ENDS
					END

-- 

Greg Youngdahl    AT&T Bell Laboratories   Naperville, IL
att!iwsgw!greg

wei@hpctdls.HP.COM (Bill Ives) (09/21/89)

   In response to your phase error problem,... I tried your
   piece of code and found the same problem.  I do have a couple of suggestions
   of fixes though.  First, instead of

      install proc near
              mov  cx, seg myproc
              ret
      install endp
      myproc  proc far
              ret
      myproc  endp

   you could switch the order of the procs so the "seg" doesn't have to
   reference a forward label.  Or you could put the "myproc" in a separate
   file module and declare it as EXTRN myproc:FAR  ... again giving the
   assembler exact resolution of its whereabouts.  Another possiblity...
   depending on what you are trying to do is to load the segment value from
   the segment name or register al la:
               mov  cx, _TEXT
                    OR
               mov  cx, cs  ; since you told the assembler to ASSUME cs:_text
    BUT if you must forward reference like the example you posted you
    can use the segment override prefix-this worked for me- although I am not
    sure what you want put into cx (see previous discussion).. The segment
    override form is:
               mov  cx, seg cs:myproc

    If you had a data segment in your example and wanted to forward reference
    to a variable in it along the same lines you would have to do:
               mov   cx, seg ds:thevarname.

    
    Hope this clears it up some.  I cannot explain why MS MASM 5.1 can't handle
    what you gave it ( IT seems a semi-smart assemebler could provide fix-ups
    for the forward reference you gave --padded with nops perhaps--).
    
    Bill Ives
    HP CTD
    #include <std-disclaimer-here>