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>