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

Passing Variables between Assembly & C functions

Hi All,

I'm more of a Assembly guy than C.

I came across this forum when I am seeking for some quick guide of sharing data registers / variables of different files of C and .a51 in a simple program.

Calling each other from C to get the function written in .a51 or vice-versa is completed. Went through c2asm2c.zip, tested and find that it worked perfectly. However, I encounter some trouble when I need to pass on some variables that need to be manipulated from .a51 to .c

My case:-

Main code is in .a51. Requires to call a function that adds 20 slightly different 8bit data bytes and then take its average (i.e. by division).

Writing the function above in .a51 is a pain due to unavailable 16bit-addition in 8051 done under Keil uV2.

My solution thought:- is to write the addition function in C so addition can be done much more easily.

Problem:- how do I pass the variables/registers defined in .a51 to the C function to be called from .a51 environment? The C function failed to recognize the similar declared register under .a51 before. Do I need to declare them under a new name OR use the similar name of data registers OR can use some global declaration of data registers. But how?

Appreciate some really cool advice if available.

Cheers,
James

Parents
  • Hi James,

    My solution is: writing your function and call it in C code, then let the Keil Translate it into ASM code. (You know how to do that, right?) You will know what you need to do in your hand written ASM code to call the C function.
    The following is just an example:

    #include <REG52.H>
    
    #define BYTE 	unsigned char
    #define WORD 	unsigned short
    
    BYTE xdata RawData[20];
    BYTE Average(BYTE * pInputData, BYTE len);
    void main (void)
    {
            BYTE Result;
    
    	while (1)
    	{
    		Result = Average(&RawData[0], 20);
    	}
    }
    
    BYTE Average(BYTE * pInputData, BYTE len)
    {
    	BYTE i;
    	WORD sum = 0;
    
    	for (i=0; i<len; i++)
    		sum += *(pInputData ++);
    
    	return (sum/len);
    }
    

    Then you can find the following result in your main.src
    	RSEG  ?XD?MAIN
            RawData:   DS   20
    ; void main (void)
    
    	RSEG  ?PR?main?MAIN
    main:
    	USING	0
    			; SOURCE LINE # 26
    ; {
    			; SOURCE LINE # 27
    ?C0001:
    ; 	BYTE Result;
    ;
    ; 	while (1)
    			; SOURCE LINE # 30
    ; 	{
    			; SOURCE LINE # 31
    ; 		Result = Average(&RawData[0], 20);
    			; SOURCE LINE # 32
    	MOV  	R3,#01H
    	MOV  	R2,#HIGH (RawData)
    	MOV  	R1,#LOW (RawData)
    	MOV  	R5,#014H
    	LCALL	_Average
    	MOV  	Result?040,R7
    ; 	}
    			; SOURCE LINE # 33
    	SJMP 	?C0001
    ?C0002:
    ; }
    			; SOURCE LINE # 34
    ?C0003:
    	RET
    ; END OF main
    
    ; BYTE Average(BYTE * pInputData, BYTE len)
    
    	RSEG  ?PR?_Average?MAIN
    _Average:
    	USING	0
    			; SOURCE LINE # 38
    	MOV  	pInputData?141,R3
    	MOV  	pInputData?141+01H,R2
    	MOV  	pInputData?141+02H,R1
    	MOV  	len?142,R5
    ; {
    			; SOURCE LINE # 39
    ; 	BYTE i;
    ; 	WORD sum = 0;
    			; SOURCE LINE # 41
    	MOV  	sum?144,#00H
    	MOV  	sum?144+01H,#00H
    ;
    ; 	for (i=0; i<len; i++)
    			; SOURCE LINE # 43
    	MOV  	i?143,#00H
    ?C0004:
    	MOV  	A,i?143
    	CLR  	C
    	SUBB 	A,len?142
    	JNC  	?C0005
    ; 		sum += *(pInputData ++);
    			; SOURCE LINE # 44
    	MOV  	R3,pInputData?141
    	INC  	pInputData?141+02H
    	MOV  	A,pInputData?141+02H
    	MOV  	R2,pInputData?141+01H
    	JNZ  	?C0008
    	INC  	pInputData?141+01H
    ?C0008:
    	DEC  	A
    	MOV  	R1,A
    	LCALL	?C?CLDPTR
    	MOV  	R7,A
    	MOV  	R6,#00H
    	MOV  	A,R7
    	ADD  	A,sum?144+01H
    	MOV  	sum?144+01H,A
    	MOV  	A,R6
    	ADDC 	A,sum?144
    	MOV  	sum?144,A
    ?C0006:
    	INC  	i?143
    	SJMP 	?C0004
    ?C0005:
    ;
    ; 	return (sum/len);
    			; SOURCE LINE # 46
    	MOV  	R7,len?142
    	MOV  	A,R7
    	MOV  	R5,A
    	MOV  	R4,#00H
    	MOV  	R6,sum?144
    	MOV  	R7,sum?144+01H
    	LCALL	?C?UIDIV
    ; }
    			; SOURCE LINE # 47
    ?C0007:
    	RET
    ; END OF _Average
    

    Hope it will help.
    Frank

Reply
  • Hi James,

    My solution is: writing your function and call it in C code, then let the Keil Translate it into ASM code. (You know how to do that, right?) You will know what you need to do in your hand written ASM code to call the C function.
    The following is just an example:

    #include <REG52.H>
    
    #define BYTE 	unsigned char
    #define WORD 	unsigned short
    
    BYTE xdata RawData[20];
    BYTE Average(BYTE * pInputData, BYTE len);
    void main (void)
    {
            BYTE Result;
    
    	while (1)
    	{
    		Result = Average(&RawData[0], 20);
    	}
    }
    
    BYTE Average(BYTE * pInputData, BYTE len)
    {
    	BYTE i;
    	WORD sum = 0;
    
    	for (i=0; i<len; i++)
    		sum += *(pInputData ++);
    
    	return (sum/len);
    }
    

    Then you can find the following result in your main.src
    	RSEG  ?XD?MAIN
            RawData:   DS   20
    ; void main (void)
    
    	RSEG  ?PR?main?MAIN
    main:
    	USING	0
    			; SOURCE LINE # 26
    ; {
    			; SOURCE LINE # 27
    ?C0001:
    ; 	BYTE Result;
    ;
    ; 	while (1)
    			; SOURCE LINE # 30
    ; 	{
    			; SOURCE LINE # 31
    ; 		Result = Average(&RawData[0], 20);
    			; SOURCE LINE # 32
    	MOV  	R3,#01H
    	MOV  	R2,#HIGH (RawData)
    	MOV  	R1,#LOW (RawData)
    	MOV  	R5,#014H
    	LCALL	_Average
    	MOV  	Result?040,R7
    ; 	}
    			; SOURCE LINE # 33
    	SJMP 	?C0001
    ?C0002:
    ; }
    			; SOURCE LINE # 34
    ?C0003:
    	RET
    ; END OF main
    
    ; BYTE Average(BYTE * pInputData, BYTE len)
    
    	RSEG  ?PR?_Average?MAIN
    _Average:
    	USING	0
    			; SOURCE LINE # 38
    	MOV  	pInputData?141,R3
    	MOV  	pInputData?141+01H,R2
    	MOV  	pInputData?141+02H,R1
    	MOV  	len?142,R5
    ; {
    			; SOURCE LINE # 39
    ; 	BYTE i;
    ; 	WORD sum = 0;
    			; SOURCE LINE # 41
    	MOV  	sum?144,#00H
    	MOV  	sum?144+01H,#00H
    ;
    ; 	for (i=0; i<len; i++)
    			; SOURCE LINE # 43
    	MOV  	i?143,#00H
    ?C0004:
    	MOV  	A,i?143
    	CLR  	C
    	SUBB 	A,len?142
    	JNC  	?C0005
    ; 		sum += *(pInputData ++);
    			; SOURCE LINE # 44
    	MOV  	R3,pInputData?141
    	INC  	pInputData?141+02H
    	MOV  	A,pInputData?141+02H
    	MOV  	R2,pInputData?141+01H
    	JNZ  	?C0008
    	INC  	pInputData?141+01H
    ?C0008:
    	DEC  	A
    	MOV  	R1,A
    	LCALL	?C?CLDPTR
    	MOV  	R7,A
    	MOV  	R6,#00H
    	MOV  	A,R7
    	ADD  	A,sum?144+01H
    	MOV  	sum?144+01H,A
    	MOV  	A,R6
    	ADDC 	A,sum?144
    	MOV  	sum?144,A
    ?C0006:
    	INC  	i?143
    	SJMP 	?C0004
    ?C0005:
    ;
    ; 	return (sum/len);
    			; SOURCE LINE # 46
    	MOV  	R7,len?142
    	MOV  	A,R7
    	MOV  	R5,A
    	MOV  	R4,#00H
    	MOV  	R6,sum?144
    	MOV  	R7,sum?144+01H
    	LCALL	?C?UIDIV
    ; }
    			; SOURCE LINE # 47
    ?C0007:
    	RET
    ; END OF _Average
    

    Hope it will help.
    Frank

Children
No data