This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

The nature of BAD RELOCATABLE EXPRESSION

hi,

Let assume that one .asm file contains next definitions:

PUBLIC FLAG1,FLAG2
FLAG1	EQU	00000001b
FLAG2	EQU	00000010b

and the second file contains next line:
	MOV	A,#(FLAG1 OR FLAG2)

When compiling, it produces A14 error:

BAD RELOCATABLE EXPRESSION:
A relocatable expression may contain only one relocatable symbol which may be a egment symbol, external symbol, or a symbol belonging to a relocatable segment.
Mathematical operations cannot be carried out on more than one relocatable symbol.

I understand the mean of this error and have found some workarounds. But could I ask: what is the nature of this limitation? Is it just from pure compiler or the reason is more complex?

Thanks,
Oleg

  • sorry,
    forgot to say that content of the second file includes external link as well:

    EXTRN NUMBER(FLAG1,FLAG2)
    
    	MOV	A,#(FLAG1 OR FLAG2)
    

    Regards,
    Oleg

  • The limitation, I think, is in just how much compuational complexity you want to burden the linker with, and how bad code is allowed to become because the assembler didn't know the value of such an expression, during its pass through the code.

    The workaround: don't hide such published EQU in the module's source --- put them into the .inc file exporting the first file's services, as SET values.

  • I have nothing about this particular case, however I have, since ages, abolished extern constants. I honestly do not remember why, but it was something like what you refer to. so, today, and since whenever, all constants are in .inc or .h files. I did ask Keil support and got an answer I could accept/understand as to why but what it was is long lost.

    Erik

  • hi,

    because the assembler didn't know the value of such an expression, during its pass through the code

    Well, I see it clean, but what is about next:

    First file:

    PUBLIC	XBUF
    ?XD?XBUF	SEGMENT XDATA
    		RSEG	?XD?XBUF
    XBUF:		DS	1024
    

    The second file:
    EXTRN	XDATA(XBUF)
    
    	MOV	A,#(LOW(XBUF) + 1)  ; line 1
    	MOV	A,#(LOW(XBUF) OR 1) ; line 2
    

    So line 1 has been passed but line 2 does not.

    Regards,
    Oleg

  • Both statements in the second file contain references that are external. This means that they are resolved by the linker.

    The linker can resolve externals and some simple mathematical operations (typically + and -). However, more sophisticated operations are not supported by the linker (actually they are not supported by the OMF since this is how the assembler and compiler pass this information to the linker).

    In line 1,

    MOV	A,#(LOW(XBUF) + 1)  ; line 1

    the linker must resolve LOW(XBUF) + 1. To send this information to the linker, the assembler adds a fixup record to the OBJ file that includes the symbol (XBUF) and a displacement (+1). For the most part, that's all the information that the assembler can store in the OMF file passed to the linker. And, in this case, the linker gets the LSB of the address of XBUF and adds 1 to it.


    In line 2,

    MOV	A,#(LOW(XBUF) OR 1) ; line 2

    the linker must resolve LOW(XBUF) OR 1. In this case, the assembler can certainly create the fixup record for the symbol (XBUF) but there is nothing in the OMF specification that supports bit masks. So, there is no way the assembler can send the OR 1 to the linker.

    Actually, I don't think there is any object module format that allows/supports unlimited manipulations with the values of external symbols.

    To do what you want, you'll need to split line 2 into the following

    MOV	A,#LOW(XBUF)
    ORL     A,#1
    

    Jon