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,<br>
    I've prepared a "short" cookbook - 3 files - C, A51 and H.<br>
    <br>
    Here you go:<br>
    A51 source file (~frame):<br>

    #include <test_h.H>      ; A51 accepts (with some restrictions) header files with SFR and other definitions
    
    ; tell the linker known symbol names:
    public  DataGroup1, DataGroup2
    public  Char_dataA,Char_dataB, Int_data, Int_dataH, Int_dataL
    public  Long_data, Long_data1, Long_data2, Long_data3, Long_data4
    public  Flags1, Flags2
    public  Flag0, Flag1, abc, Flag7
    public  Bit_var1, Bit_var2
    public  Char_array
    public  Char_idata, Char_xdata
    
    public  my_function_A51, _my_regpar_function_A51
    
    ; tell the linker external symbol names needed for this file
    extrn   bit     (bit_var1_C, bit_var2_C)        ; bit variables defined in a C file and used here
    extrn   data    (data_var1_C, data_var2_C)      ; data variables defined in a C file and used here
    extrn   idata   (idata_var_C)                   ; idata variables defined in a C file and used here
    extrn   xdata   (xdata_var_C)                   ; xdata variables defined in a C file, also for pdata vars
    extrn   code    (func_C, _func_regpar_C)        ; function defined in a C file and used here
                                                    ; for func_C(void)
                                                    ; and func_regpar_C(..params) - in C without underscore!
    ;extrn   number  (MAX, MIN)                     ; defined in another asm file (here it doesn't exist)
    
    ; Absolute
    
    ;---
    ;These are the "hard" addresses for (only) byte addressable variables
    DataGroup1      DATA    0x050           ; (why is this simple variable called ..Group?)
    DataGroup2      DATA    0x051
    
    ;This is the "hard" address for a bit addressable variable:
    Flags1          DATA    0x020           ;contains Timer0IntHap, sleepingnow and etc
    
    
    ; Relative
    ; define data, bdata, idata, xdata, pdata relative segments
    
    ;---                                            ; "?BA?BDATA_SEG" is YOUR name of the segment
    ?BA?BDATA_SEG   segment data    bitaddressable  ; you can specify a bitaddressable
                                                    ; relocatable data segment this way
            rseg    ?BA?BDATA_SEG           ; the specified segment starts here
    
    Flags2:         ds      1               ; linker will locate it in the bitaddressable
                                            ; internal RAM area (20H to 2FH); here probably 21H
    Flag0   bit     Flags2.0                ; you can specify names
    Flag1   bit     Flags2.1                ; for particular bit this way
    abc     bit     Flags2.3                ; the same of course for Flags1 defined above
    ;...
    Flag7   bit     Flags2.7
    
    
    ;---                                    ; "?BI?BIT_SEG" is YOUR name of the segment
    ?BI?BIT_SEG     segment bit             ; you can specify a relocatable
                                            ; bit segment this way
            rseg    ?BI?BIT_SEG             ; the specified segment starts here
    
    Bit_var1:       dbit    1               ; bit variable1, linker will locate it
                                            ; in the bitaddressable area 20h to 2FH (bit addresses 0 to 7FH)
    Bit_var2:       dbit    1               ; bit variable2
    
    
    ;---                                    ; "?DT?DATA_SEG" is YOUR name of the segment
    ?DT?DATA_SEG    segment data            ; you can specify a relocatable data segment
                                            ; this way (linker will locate it in 0H to 7FH area)
            rseg    ?DT?DATA_SEG            ; the specified data segment starts here
    
    Char_dataA:     ds      1               ; 1st (unsigned) char variable
    Char_dataB:     ds      1               ; 2nd (unsigned) char variable
    
    Int_data:       ds      2               ; (unsigned) int variable
    Int_dataH       data    Int_data        ; MSB (Big Endian manner)
    Int_dataL       data    Int_data+1      ; LSB this way you can specify components of longer types
    
    Long_data:      ds      4               ; (unsigned) long variable
    Long_data1      data    Long_data       ; MSB ...
    Long_data2      data    Long_data+1     ; particular components
    Long_data3      data    Long_data+2     ; of long variable
    Long_data4      data    Long_data+3     ; ... LSB
    
    Char_array:     ds      A_LENGTH        ; array of chars (size in the included header file)
                                            ; just for illustration, needn't be defined
    char_array0     data    Char_array      ; 1st - Char_array[0]
    ;...
    char_array4     data    Char_array+4    ; 5th - Char_array[4]
    
    ;---                                    ; "?ID?IDATA_SEG" is YOUR name of the segment
    ?ID?IDATA_SEG   segment idata           ; you can specify a relocatable idata segment
                                            ; this way (linker will locate it in 0H to FFH area, if available)
                                            ; behind the last DATA segment
            rseg    ?ID?IDATA_SEG           ; the specified xdata segment starts here
    
    Char_idata:     ds      1               ; (unsigned) char variable in IDATA
    
    ;---                                    ; "?XD?XDATA_SEG" is YOUR name of the segment
    ?XD?XDATA_SEG   segment xdata ;inpage   ; you can specify a relocatable xdata segment
                                            ; this way (linker will locate it in available XRAM area)
                                            ; optionable "inpage" (omit the semicolon) tells the linker
                                            ; to locate it in a memory page
            rseg    ?XD?XDATA_SEG           ; the specified xdata segment starts here
    
    Char_xdata:     ds      1               ; (unsigned) char variable in XDATA
    
    
    ; define program segment(s)
    ;---                                    ; "?PR?PROG_SEG" is YOUR name of the segment
    ?PR?PROG_SEG    segment code            ; you can specify a relocatable
                                            ; code (program) segment this way
            rseg    ?PR?PROG_SEG            ; the specified segment starts here
    
    my_function_A51:
    ; A51 function code (here empty)
            ret
    
    _my_regpar_function_A51:                ; name of an "A51 written" function passing parameters
    ; take the (register)                   ; in registers starts with the underline character: _
    ; passed parameters (here in R7)
            mov     Char_dataB,r7           ; my_regpar_function_A51(uchar x)
                                            ; {
                                            ;   Char_dataB = x;
                                            ; }
            ret
    ; bla bla ...
            call    func_C                  ; function without parameters written in C
    
    ; prepare actual parameters in appropriate registers
            call    _func_regpar_C          ; function with parameters written in C
    ; bla bla
    
            end
    

    ... to be continued :-(

Reply
  • Hi James,<br>
    I've prepared a "short" cookbook - 3 files - C, A51 and H.<br>
    <br>
    Here you go:<br>
    A51 source file (~frame):<br>

    #include <test_h.H>      ; A51 accepts (with some restrictions) header files with SFR and other definitions
    
    ; tell the linker known symbol names:
    public  DataGroup1, DataGroup2
    public  Char_dataA,Char_dataB, Int_data, Int_dataH, Int_dataL
    public  Long_data, Long_data1, Long_data2, Long_data3, Long_data4
    public  Flags1, Flags2
    public  Flag0, Flag1, abc, Flag7
    public  Bit_var1, Bit_var2
    public  Char_array
    public  Char_idata, Char_xdata
    
    public  my_function_A51, _my_regpar_function_A51
    
    ; tell the linker external symbol names needed for this file
    extrn   bit     (bit_var1_C, bit_var2_C)        ; bit variables defined in a C file and used here
    extrn   data    (data_var1_C, data_var2_C)      ; data variables defined in a C file and used here
    extrn   idata   (idata_var_C)                   ; idata variables defined in a C file and used here
    extrn   xdata   (xdata_var_C)                   ; xdata variables defined in a C file, also for pdata vars
    extrn   code    (func_C, _func_regpar_C)        ; function defined in a C file and used here
                                                    ; for func_C(void)
                                                    ; and func_regpar_C(..params) - in C without underscore!
    ;extrn   number  (MAX, MIN)                     ; defined in another asm file (here it doesn't exist)
    
    ; Absolute
    
    ;---
    ;These are the "hard" addresses for (only) byte addressable variables
    DataGroup1      DATA    0x050           ; (why is this simple variable called ..Group?)
    DataGroup2      DATA    0x051
    
    ;This is the "hard" address for a bit addressable variable:
    Flags1          DATA    0x020           ;contains Timer0IntHap, sleepingnow and etc
    
    
    ; Relative
    ; define data, bdata, idata, xdata, pdata relative segments
    
    ;---                                            ; "?BA?BDATA_SEG" is YOUR name of the segment
    ?BA?BDATA_SEG   segment data    bitaddressable  ; you can specify a bitaddressable
                                                    ; relocatable data segment this way
            rseg    ?BA?BDATA_SEG           ; the specified segment starts here
    
    Flags2:         ds      1               ; linker will locate it in the bitaddressable
                                            ; internal RAM area (20H to 2FH); here probably 21H
    Flag0   bit     Flags2.0                ; you can specify names
    Flag1   bit     Flags2.1                ; for particular bit this way
    abc     bit     Flags2.3                ; the same of course for Flags1 defined above
    ;...
    Flag7   bit     Flags2.7
    
    
    ;---                                    ; "?BI?BIT_SEG" is YOUR name of the segment
    ?BI?BIT_SEG     segment bit             ; you can specify a relocatable
                                            ; bit segment this way
            rseg    ?BI?BIT_SEG             ; the specified segment starts here
    
    Bit_var1:       dbit    1               ; bit variable1, linker will locate it
                                            ; in the bitaddressable area 20h to 2FH (bit addresses 0 to 7FH)
    Bit_var2:       dbit    1               ; bit variable2
    
    
    ;---                                    ; "?DT?DATA_SEG" is YOUR name of the segment
    ?DT?DATA_SEG    segment data            ; you can specify a relocatable data segment
                                            ; this way (linker will locate it in 0H to 7FH area)
            rseg    ?DT?DATA_SEG            ; the specified data segment starts here
    
    Char_dataA:     ds      1               ; 1st (unsigned) char variable
    Char_dataB:     ds      1               ; 2nd (unsigned) char variable
    
    Int_data:       ds      2               ; (unsigned) int variable
    Int_dataH       data    Int_data        ; MSB (Big Endian manner)
    Int_dataL       data    Int_data+1      ; LSB this way you can specify components of longer types
    
    Long_data:      ds      4               ; (unsigned) long variable
    Long_data1      data    Long_data       ; MSB ...
    Long_data2      data    Long_data+1     ; particular components
    Long_data3      data    Long_data+2     ; of long variable
    Long_data4      data    Long_data+3     ; ... LSB
    
    Char_array:     ds      A_LENGTH        ; array of chars (size in the included header file)
                                            ; just for illustration, needn't be defined
    char_array0     data    Char_array      ; 1st - Char_array[0]
    ;...
    char_array4     data    Char_array+4    ; 5th - Char_array[4]
    
    ;---                                    ; "?ID?IDATA_SEG" is YOUR name of the segment
    ?ID?IDATA_SEG   segment idata           ; you can specify a relocatable idata segment
                                            ; this way (linker will locate it in 0H to FFH area, if available)
                                            ; behind the last DATA segment
            rseg    ?ID?IDATA_SEG           ; the specified xdata segment starts here
    
    Char_idata:     ds      1               ; (unsigned) char variable in IDATA
    
    ;---                                    ; "?XD?XDATA_SEG" is YOUR name of the segment
    ?XD?XDATA_SEG   segment xdata ;inpage   ; you can specify a relocatable xdata segment
                                            ; this way (linker will locate it in available XRAM area)
                                            ; optionable "inpage" (omit the semicolon) tells the linker
                                            ; to locate it in a memory page
            rseg    ?XD?XDATA_SEG           ; the specified xdata segment starts here
    
    Char_xdata:     ds      1               ; (unsigned) char variable in XDATA
    
    
    ; define program segment(s)
    ;---                                    ; "?PR?PROG_SEG" is YOUR name of the segment
    ?PR?PROG_SEG    segment code            ; you can specify a relocatable
                                            ; code (program) segment this way
            rseg    ?PR?PROG_SEG            ; the specified segment starts here
    
    my_function_A51:
    ; A51 function code (here empty)
            ret
    
    _my_regpar_function_A51:                ; name of an "A51 written" function passing parameters
    ; take the (register)                   ; in registers starts with the underline character: _
    ; passed parameters (here in R7)
            mov     Char_dataB,r7           ; my_regpar_function_A51(uchar x)
                                            ; {
                                            ;   Char_dataB = x;
                                            ; }
            ret
    ; bla bla ...
            call    func_C                  ; function without parameters written in C
    
    ; prepare actual parameters in appropriate registers
            call    _func_regpar_C          ; function with parameters written in C
    ; bla bla
    
            end
    

    ... to be continued :-(

Children
No data