- •Chapter 1. Introduction
- •Support for all 8051 Variants
- •Books About the C Language
- •Chapter 2. Compiling with the Cx51 Compiler
- •Environment Variables
- •Running Cx51 from the Command Prompt
- •ERRORLEVEL
- •Cx51 Output Files
- •Control Directives
- •Directive Categories
- •Reference
- •Chapter 3. Language Extensions
- •Keywords
- •Memory Areas
- •Program Memory
- •Internal Data Memory
- •External Data Memory
- •Far Memory
- •Special Function Register Memory
- •Memory Models
- •Small Model
- •Compact Model
- •Large Model
- •Memory Types
- •Explicitly Declared Memory Types
- •Implicit Memory Types
- •Data Types
- •Bit Types
- •Special Function Registers
- •sbit
- •Absolute Variable Location
- •Pointers
- •Generic Pointers
- •Pointer Conversions
- •Abstract Pointers
- •Function Declarations
- •Function Parameters and the Stack
- •Passing Parameters in Registers
- •Function Return Values
- •Specifying the Memory Model for a Function
- •Specifying the Register Bank for a Function
- •Register Bank Access
- •Interrupt Functions
- •Reentrant Functions
- •Chapter 4. Preprocessor
- •Directives
- •Stringize Operator
- •Predefined Macro Constants
- •Chapter 5. 8051 Derivatives
- •Analog Devices MicroConverter B2 Series
- •Atmel 89x8252 and Variants
- •Dallas 80C320, 420, 520, and 530
- •Arithmetic Accelerator
- •Data Pointers
- •Library Routines
- •Philips 8xC750, 8xC751, and 8xC752
- •Philips 80C51MX Architecture
- •Philips and Atmel WM Dual DPTR
- •Customization Files
- •STARTUP.A51
- •INIT.A51
- •XBANKING.A51
- •Basic I/O Functions
- •Memory Allocation Functions
- •Optimizer
- •General Optimizations
- •Options for Code Generation
- •Segment Naming Conventions
- •Data Objects
- •Program Objects
- •Interfacing C Programs to Assembler
- •Function Parameters
- •Parameter Passing in Registers
- •Parameter Passing in Fixed Memory Locations
- •Function Return Values
- •Using the SRC Directive
- •Register Usage
- •Overlaying Segments
- •Example Routines
- •Small Model Example
- •Compact Model Example
- •Large Model Example
- •Data Storage Formats
- •Bit Variables
- •Signed and Unsigned Long Integers
- •Generic and Far Pointers
- •Floating-point Numbers
- •Accessing Absolute Memory Locations
- •Absolute Memory Access Macros
- •Linker Location Controls
- •The _at_ Keyword
- •Debugging
- •Chapter 7. Error Messages
- •Fatal Errors
- •Actions
- •Errors
- •Syntax and Semantic Errors
- •Warnings
- •Chapter 8. Library Reference
- •Intrinsic Routines
- •Library Files
- •Standard Types
- •va_list
- •Absolute Memory Access Macros
- •CBYTE
- •CWORD
- •DBYTE
- •DWORD
- •FARRAY, FCARRAY
- •FVAR, FCVAR,
- •PBYTE
- •PWORD
- •XBYTE
- •XWORD
- •Routines by Category
- •Buffer Manipulation
- •Character Conversion and Classification
- •Data Conversion
- •Math Routines
- •Memory Allocation Routines
- •Stream Input and Output Routines
- •String Manipulation Routines
- •Miscellaneous Routines
- •Include Files
- •8051 Special Function Register Include Files
- •ABSACC.H
- •ASSERT.H
- •CTYPE.H
- •INTRINS.H
- •MATH.H
- •SETJMP.H
- •STDARG.H
- •STDDEF.H
- •STDIO.H
- •STDLIB.H
- •STRING.H
- •Reference
- •Compiler-related Differences
- •Library-related Differences
- •Appendix B. Version Differences
- •Version 6.0 Differences
- •Version 5 Differences
- •Version 4 Differences
- •Version 3.4 Differences
- •Version 3.2 Differences
- •Version 3.0 Differences
- •Version 2 Differences
- •Appendix C. Writing Optimum Code
- •Memory Model
- •Variable Location
- •Variable Size
- •Unsigned Types
- •Local Variables
- •Other Sources
- •Appendix D. Compiler Limits
- •Appendix E. Byte Ordering
- •Recursive Code Reference Error
- •Problems Using the printf Routines
- •Uncalled Functions
- •Using Monitor-51
- •Trouble with the bdata Memory Type
- •Function Pointers
- •Glossary
- •Index
Keil Software — Cx51 Compiler User’s Guide |
163 |
|
|
Interfacing C Programs to Assembler
You can easily interface your programs to routines written in 8051 Assembler. The A51 Assembler is an 8051 macro assembler that emits object modules in OMF-51 format. By observing a few programming rules, you can call assembly routines from C and vice versa. Public variables declared in the assembly module are available to your C programs.
There are several reasons to call an assembly routine from your C program.
You may have assembly code already written that you wish to use
You may need to improve the speed of a particular function
You may want to manipulate SFRs or memory-mapped I/O devices directly from assembly
This section describes how to write assembly routines that can be directly interfaced to C programs.
For an assembly routine to be called from C, it must be aware of the parameter passing and return value conventions used in C functions. For all practical purposes, it must appear to be a C function.
Function Parameters
By default, C functions pass up to three parameters in registers. The remaining
parameters are passed in fixed memory locations. You may use the directive 6 NOREGPARMS to disable parameter passing in registers. Parameters are
passed in fixed memory locations if parameter passing in registers is disabled or if there are too many parameters to fit in registers. Functions that pass parameters in registers are flagged by the Cx51 compiler with an underscore character (‘_’) prefixed to the function name at code generation time. Functions that pass parameters only in fixed memory locations are not prefixed with an underscore. Refer to “Using the SRC Directive” on page 166 for an example.
164 |
Chapter 6. Advanced Programming Techniques |
|
|
Parameter Passing in Registers
C functions may pass parameters in registers and fixed memory locations. A maximum of 3 parameters may be passed in registers. All other parameters are passed using fixed memory locations. The following tables define what registers are used for passing parameters.
Arg Number |
char, 1-byte ptr |
int, 2-byte ptr |
long, float |
generic ptr |
1 |
R7 |
R6 & R7 |
R4—R7 |
R1—R3 |
|
|
(MSB in R6, |
|
(Mem type in R3, |
|
|
LSB in R7) |
|
MSB in R2, |
|
|
|
|
LSB in R1) |
2 |
R5 |
R4 & R5 |
R4—R7 |
R1—R3 |
|
|
(MSB in R4, |
|
(Mem type in R3, |
|
|
LSB in R5) |
|
MSB in R2, |
|
|
|
|
LSB in R1) |
3 |
R3 |
R2 & R3 |
|
R1—R3 |
|
|
(MSB in R2, |
|
(Mem type in R3, |
|
|
LSB in R3) |
|
MSB in R2, |
|
|
|
|
LSB in R1) |
The following examples clarify how registers are selected for parameter passing.
|
|
Declaration |
Description |
|
|
|
|
|
func1 ( |
The first and only argument, a, is passed in registers R6 and R7. |
|
||
|
|
int a) |
|
b, |
is passed in registers R6 and R7. The second |
|
|
|
func2 ( |
The first argument, |
|
||
|
|
int b, |
argument, c, is passed in registers R4 and R5. The third argument, d, is |
|
||
6 |
|
|||||
|
int c, |
passed in registers R1, R2, and R3. |
|
|||
|
int *d) |
|
e, |
is passed in registers R4, R5, R6, and R7. The |
|
|
|
func3 ( |
The first argument, |
|
|||
|
|
long e, |
second argument, |
f, |
cannot be located in registers since those available for |
|
|
|
long f) |
a second parameter with a type of long are already used by the first argument. |
|
||
|
|
|
This parameter is passed using fixed memory locations. |
|
||
|
|
func4 ( |
The first argument, |
g, |
passed in registers R4, R5, R6, and R7. The second |
|
|
|
float g, |
parameter, h, cannot be passed in registers and is passed in fixed memory |
|
||
|
|
char h) |
locations. |
|
|
|
|
|
|
|
|
|
|
Keil Software — Cx51 Compiler User’s Guide |
165 |
|
|
Parameter Passing in Fixed Memory Locations
Parameters passed to assembly routines in fixed memory locations use segments named ?function_name?BYTE and ?function_name?BIT to hold the parameter values passed to the function function_name. Bit parameters are copied into the ?function_name?BIT segment prior to calling the function. All other parameters are copied into the ?function_name?BYTE segment. All parameters are assigned space in these segments even if they are passed using registers. Parameters are stored in the order in which they are declared in each respective segment.
The fixed memory locations used for parameter passing may be in internal data memory or external data memory depending upon the memory model used. The SMALL memory model is the most efficient and uses internal data memory for parameter segments. The COMPACT and LARGE models use external data memory for the parameter passing segments.
Function Return Values
Function return values are always passed using CPU registers. The following table lists the possible return types and the registers used for each.
Return Type |
Register |
Description |
|
|
Bit |
Carry Flag |
Single bit returned in the carry flag |
|
|
char / unsigned char, |
R7 |
Single byte typed returned in R7 |
|
|
1-byte pointer |
|
|
|
6 |
int / unsigned int, |
R6 & R7 |
MSB in R6, LSB in R7 |
|
|
2-byte ptr |
|
|
|
|
long / unsigned long |
R4-R7 |
MSB in R4, LSB in R7 |
|
|
Float |
R4-R7 |
32-Bit IEEE format |
|
|
|
||||
generic pointer |
R1-R3 |
Memory type in R3, MSB R2, LSB R1 |
|
|
166 |
Chapter 6. Advanced Programming Techniques |
|
|
Using the SRC Directive
The Cx51 compiler can create assembly source files you assemble with the A51 Assembler. These files may be useful when you want to determine the argument passing conventions between C and assembly.
To create an assembly source file, you must use the SRC directive with the Cx51 compiler. For example:
#pragma SRC #pragma SMALL
unsigned int asmfunc1 ( unsigned int arg)
{
return (1 + arg);
}
generates the following assembly output file when compiled using the SRC directive.
; ASM1.SRC generated from: ASM1.C
NAME ASM1
?PR?_asmfunc1?ASM1 SEGMENT CODE
PUBLIC _asmfunc1
;#pragma SRC
;#pragma SMALL
;unsigned int asmfunc1 (
6 |
RSEG |
?PR?_asmfunc1?ASM1 |
USING |
0 |
|
_asmfunc1: |
|
|
;---- Variable 'arg?00' assigned to Register 'R6/R7' ---- |
||
|
|
; SOURCE LINE # 4 |
|
|
; SOURCE LINE # 6 |
|
; return (1 + arg); |
|
|
|
; SOURCE LINE # 7 |
|
MOV |
A,R7 |
|
ADD |
A,#01H |
|
MOV |
R7,A |
|
CLR |
A |
|
ADDC |
A,R6 |
|
MOV |
R6,A |
; }
; SOURCE LINE # 8
?C0001:
RET ; END OF _asmfunc1
END
Keil Software — Cx51 Compiler User’s Guide |
167 |
|
|
In this example, note that the function name, asmfunc1, is prefixed with an underscore character signifying that arguments are passed in registers. The arg parameter is passed using R6 and R7.
The following example shows the assembly source generated for the same function; however, register parameter passing has been disabled using the
NOREGPARMS directive.
; ASM2.SRC generated from: ASM2.C
NAME |
ASM2 |
|
?PR?asmfunc1?ASM2 |
SEGMENT CODE |
|
?DT?asmfunc1?ASM2 |
SEGMENT DATA |
|
PUBLIC |
?asmfunc1?BYTE |
|
PUBLIC |
asmfunc1 |
|
RSEG ?DT?asmfunc1?ASM2
?asmfunc1?BYTE: |
|
arg?00: |
DS 2 |
;#pragma SRC
;#pragma SMALL
;#pragma NOREGPARMS
;unsigned int asmfunc1 (
RSEG ?PR?asmfunc1?ASM2
USING 0
asmfunc1: |
|
|
|
; SOURCE LINE # 5 |
|
|
; SOURCE LINE # 7 |
|
; return (1 + arg); |
|
|
|
; SOURCE LINE # 8 |
|
MOV |
A,arg?00+01H |
|
ADD |
A,#01H |
6 |
MOV |
R7,A |
|
CLR |
A |
|
ADDC |
A,arg?00 |
|
MOV |
R6,A |
|
; }
; SOURCE LINE # 9
?C0001:
RET ; END OF asmfunc1
END
Note in this example that the function name, asmfunc1, is not prefixed with an underscore character and that the arg parameter is passed in the
?asmfunc1?BYTE segment.