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

Can't link assemler code with c-code

I'm not that much into assemler, so I try to reuse existing asm-code as i2c-driver. I've found original Philips code for that. I try now to link it with c-code but get always linker warnings.



Any help appreciated!



NAME . . . . . . . . . USAGE    MODULE NAMES
--------------------------------------------

?C_START . . . . . . . CODE;    ** L51 GENERATED **  ?C_STARTUP
?C_STARTUP . . . . . . CODE;    ?C_STARTUP  ASMS
?IIC_TEST_DEVICE . . . CODE;    IIC_DRIVER
?IIC_TEST_DEVICE?BYTE. DATA;    IIC_DRIVER
?INIT_IIC?BYTE . . . . DATA;    IIC_DRIVER
?_IIC_WRITE_SUB?BYTE . ILLEGAL  ** UNRESOLVED **  ASMS
IIC_ERROR. . . . . . . BIT;     IIC_DRIVER
MAIN . . . . . . . . . CODE;    ASMS
_IIC_WRITE_SUB . . . . ILLEGAL  ** UNRESOLVED **  ASMS
_INIT_IIC. . . . . . . CODE;    IIC_DRIVER  ASMS

*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
    SYMBOL:  _IIC_WRITE_SUB
    MODULE:  asms.obj (ASMS)

*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
    SYMBOL:  ?_IIC_WRITE_SUB?BYTE
    MODULE:  asms.obj (ASMS)

*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
    SYMBOL:  ?_IIC_WRITE_SUB?BYTE
    MODULE:  asms.obj (ASMS)
    ADDRESS: 0277H

*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
    SYMBOL:  _IIC_WRITE_SUB
    MODULE:  asms.obj (ASMS)
    ADDRESS: 027FH 


Here my c-code:

#include <REG552.H>
#include "iic.h"

#define myIICaddr 0x55		// my own i2c slave address


/*------------------------------------------------
MAIN C Function
------------------------------------------------*/
void main (void)
{
	unsigned char reg = 0;

	// Init routines
    Init_IIC(myIICaddr);

	// set control-register: stop counting, enable alarm
	reg = 0xC4;
	if(IIC_Write_Sub(RTC_ADDRESS, 1,  , 0x00) != I2C_OK)
	{
		// error
	}

	while (1)
	{
		;
	}
}


and the beginning of the asm-code:

$LIST
$REGISTERBANK (0,1)
$NOSYMBOLS
$PAGEWIDTH (130)
NAME    IIC_DRIVER


;
;       Includes: EQREG652.ASM
;
$NOLIST
$INCLUDE (EQREG652.ASM)
$LIST
;
; Public labels defined in this Module:
; *************************************
        public  ?IIC_Test_Device
        public  ?IIC_Test_Device?BYTE
        public  _Init_IIC
        public  ?Init_IIC?BYTE
;
$EJECT
;
...snipp...

?BI?IICBit      Segment Bit
                Rseg    ?BI?IICBit
;
                public  IIC_Error
IIC_Error:      dbit    1               ; IIC Error Bit
;
?BA?IICBitAdr       Segment Data BitAddressable
                Rseg    ?BA?IICBitAdr
;
IICCntrl:       ds      1               ; Bit Addressable IIC Control Register
;
?DT?IICPar          Segment Data
                Rseg    ?DT?IICPar

?IIC_Test_Device?BYTE:
?IIC_Write?BYTE:
?Init_IIC?BYTE:
;
SlaveAddress:   ds      1               ; Slave Address Include R/W
DataCount1:     ds      1               ; Block 1 Count
DataIndex1:     ds      1               ; Block 1 Transfer Buffer Address
SubAddress:     ds      1               ; Sub Address ( If Any )
DataCount2:     ds      1               ; Block 2 Count
DataIndex2:     ds      1               ; Block 2 Transfer Buffer Address
;
$EJECT
;
$EJECT
IICCode         Segment Code InBlock
                Rseg    IICCode
;

...snipp...

*****************************************************************
;       * Init_IIC:                                                     *
;       *    PROCEDURE ( OwnSlaveAddress ) ;                            *
;       *    DECLARE OwnSlaveAddress BYTE ;                             *
;       *                                                               *
;       *    Initialises the IIC SIO1 data, sets the Own Slave Address  *
;       *                                                               *
;       *    NOTE: This procedure must be called                        *
;       *          after power on before use of any other IIC procedure *
;       *****************************************************************
_Init_IIC:       mov     s1adr,SlaveAddress              ; Setup Own Slave Address
                mov     s1con,#NSTA_NSTO_AA             ; Assert Acknowledge on Slave Address
                mov     IICCntrl,#0                     ; Initialise Control / Status Register
                setb    es1                             ; Enable SIO1 Interrupt

Parents
  • To export a symbol from an assembler module, you need to declare it "public". Near the top of the assembly file you posted, I see:

    ; Public labels defined in this Module:
    ; *************************************
            public  ?IIC_Test_Device
            public  ?IIC_Test_Device?BYTE
            public  _Init_IIC
            public  ?Init_IIC?BYTE
    

    which doesn't list _IIC_WRITE_SUB or ?IIC_WRITE_SUB?BYTE. If there's not a "public" declaration somewhere, the symbol will remain a deep, dark, secret of this module, never to be seen by the linker. Add the symbols to the public list and rebuild.

    Not that I do a lot of assembler, either, but I prefer to keep my "publics" next to the actual definitions of the symbols, so I don't have to go find another table somewhere every time I add or change a routine. Some people, on the other hand, like the convenience of having all the publics grouped up top, kind of like a mini header file to declare what's availabe for use in that module without having to search.

    For reasons which I've forgotten, C implementations typically prepend an underscore to the "real" name of a function in the object code. So, your C function "MyFunc" will show up as the linker symbol "_MyFunc".

    The ? thing is a Keil convention. For reasons best known to them, they like question marks instead of underscores for separating components of names. The question mark is actually not syntactically significant to the assembler, C compiler, or linker. It's just another character that's part of the identifier, and the actual names follow a convention using this unusual character to delimit segment types and module names.

Reply
  • To export a symbol from an assembler module, you need to declare it "public". Near the top of the assembly file you posted, I see:

    ; Public labels defined in this Module:
    ; *************************************
            public  ?IIC_Test_Device
            public  ?IIC_Test_Device?BYTE
            public  _Init_IIC
            public  ?Init_IIC?BYTE
    

    which doesn't list _IIC_WRITE_SUB or ?IIC_WRITE_SUB?BYTE. If there's not a "public" declaration somewhere, the symbol will remain a deep, dark, secret of this module, never to be seen by the linker. Add the symbols to the public list and rebuild.

    Not that I do a lot of assembler, either, but I prefer to keep my "publics" next to the actual definitions of the symbols, so I don't have to go find another table somewhere every time I add or change a routine. Some people, on the other hand, like the convenience of having all the publics grouped up top, kind of like a mini header file to declare what's availabe for use in that module without having to search.

    For reasons which I've forgotten, C implementations typically prepend an underscore to the "real" name of a function in the object code. So, your C function "MyFunc" will show up as the linker symbol "_MyFunc".

    The ? thing is a Keil convention. For reasons best known to them, they like question marks instead of underscores for separating components of names. The question mark is actually not syntactically significant to the assembler, C compiler, or linker. It's just another character that's part of the identifier, and the actual names follow a convention using this unusual character to delimit segment types and module names.

Children
No data