📄 mc.doc
字号:
eg: #include /mc/stdio.h
NOTE: The above quirks do not apply when the external
pre-processor (MCP) is used.
The appearance of a variable name in the argument list for a
function declaration serves only to identify that variables
location on the stack. MICRO-C will not define the variable unless
it is explicitly declared (between the argument list and the main
function body). In other words, all arguments to a function must
be explicitly declared.
MICRO-C is more strict about its handling of the ADDRESS
operator ('&') than most other compilers. It will produce an error
message if you attempt to take the address of a value which is
already a fixed address (such as an array name without a full set
of indicies). Since an address is already produced in such cases,
simply drop the '&'.
The 'x' in '0x' and '\x' is accepted in lower case only.
MICRO-C Page: 18
When operating on pointers, MICRO-C only scales the increment
(++), decrement (--) and index ([]) operations to account for the
size of the pointer:
eg: char cptr; /* pointer to character */
int cptr; /* pointer to integer */
++cptr; /* Advance one character */
++iptr; /* Advance one integer */
cptr[10]; /* Access the tenth character */
iptr[10]; /* Access the tenth integer */
cptr += 10; /* Advance 10 characters */
iptr += 10; /* Advance ONLY FIVE integers */
NOTE: A portable way to advance "iptr" by integers is:
iptr = &iptr[10]; /* Advance 10 integers */
When using MICRO-C to create a function which will contain
assembly language code, remember that MICRO-C allocates all local
variables at the beginning of a function definition, and will not
generate the function entry code until a non-declarative statement
is encountered. In particular, since "#asm" is handled by the
pre-processor and not seen as a statement by the parser, you
should use a "null" statement (';') to ensure that the entry code
is generated prior to using "#asm" at the beginning of a function.
eg: func()
{ ; /* ensures "entry" code is generated */
#asm
assembly statements
#endasm
}
Also note, that MICRO-C will not output external declarations
to the output file for any variables or functions which are
declared as "extern", unless that symbol is actually referenced in
the 'C' source code. This prevents "extern" declarations in system
header files (such as "stdio.h") which are used as prototypes for
some library functions from causing those functions to be loaded
into the object file. Therefore, any "extern" symbols which are
referenced only by assembly code (using "#asm") must be declared
in assembly code, not by the MICRO-C "extern" statement.
MICRO-C Page: 19
Unlike some 'C' compilers, MICRO-C will process character
expressions using only BYTE values. Character values are not
promoted to INT unless there is an INT value involved in the
expression. This results in much more efficent code when dealing
with characters, particularily on small processors which have
limited 16 bit instructions. Consider the statement:
return c + 1;
On some compilers, this will sign extend the character variable
'c' into an integer value, and then ADD an integer 1 and return
the result. MICRO-C will ADD the character variable and a
character 1, and then promote the result to INT before returning
it (results of expressions as operands to 'return' are always
promoted to int).
Unfortunately, programs have been written which rely on the
automatic promotion of characters to INTs to work properly. The
most common source of problems is code which attempts to treat
CHAR variables as UNSIGNED values (older compilers did not support
UNSIGNED CHAR). For example:
return c & 255;
In a compiler which always evaluates character expressions as
INT, the above statement will extract the value of 'c' as positive
integer ranging from 0 to 255.
In MICRO-C, ANDing a character with 255 results in the same
character, which gets promoted to an integer value ranging from
-128 to 127. To force the promotion within the expression, you
could CAST the variable to an INT:
return (int)c & 255;
The same objective can be achieved in a more efficent (and
correct) manner by declaring the variable 'c' as UNSIGNED CHAR, or
by CASTing the variable to an UNSIGNED value:
return (unsigned)c;
Note that this is not only more clearly shows the intent of the
programmer, but also results is more efficent code generated.
MICRO-C Page: 20
3. ADVANCED TOPICS
This section provides information on the more advanced aspects of
MICRO-C, which is generally not needed for casual use of the
language.
3.1 Conversion Rules
MICRO-C keep track of the "type" of each value used in all
expressions. This type identifies certain characteristics of the
value, such as size range (8/16 bits), numeric scope
(signed/unsigned), reference (value/pointer) etc.
When an operation is performed on two values which have
identical "types", MICRO-C assigns that same "type" to the result.
When the two value "types" involved in an operation are
different, MICRO-C calculates the "type" of the result using the
following rules:
3.1.1 Size range
If both values are direct (not pointer) references, the
result will be 8 bits only if both values were 8 bits. If
either value was 16 bits, the result will be 16 bits.
If one value is a pointer, and the other is direct, the
result will be a pointer to the same size value as the original
pointer.
If both values were pointers, the result will be a pointer
to 16 bits only if both original pointers referenced 16 bit
values. If either pointer referenced an 8 bit value, the result
will reference an 8 bit value.
3.1.2 Numeric Scope
The result of an expression is considered to be signed only
if both original values were signed. If either value was an
unsigned value, the result is unsigned.
3.1.3 Reference
If either of the original values was a pointer, the result
will be a pointer.
Note that this "calculated" result type is used for partial
results within an expression. Whenever a symbol such as a variable
or function is referenced, the type of that symbol is taken from
its declaration, no matter what "type" of value was last stored
(variable) or returned (function).
MICRO-C Page: 21
3.2 Assembly Language Interface
Assembly language programs may be called from 'C' functions and
vice versa. These programs may be in the form of "#asm" statements
in the 'C' source code, or separately linked modules.
When MICRO-C calls any routine ('C' or assembler), it first
pushes all arguments to the routine onto the processor stack, in
the order in which they occur in the argument list to the
function. This means that the LAST argument to the function is
LOWEST on the processor stack.
Arguments are always pushed as 16 bit values. Character values
are extended to 16 bits, and arrays are passed as 16 bit pointers
to the array. (MICRO-C knows that arrays which are arguments are
actually pointers, and automatically references through the
pointer).
After pushing the arguments, MICRO-C then generates a machine
language subroutine call, thereby executing the code of the
routine.
Since the compiler uses the ACCUMULATOR and INDEX REGISTER, it
will automatically save them (if necessary) during processing of
the arguments to the function (even if no arguments are present),
and therefore these registers do not have to be preserved by the
called routine.
NOTE that any other registers used by the code generation
routines (register variables etc) will not be saved by MICRO-C,
and should be preserved by called functions if their content is to
be relied on between function calls.
Once the called routine returns, the arguments are removed from
the stack by the calling program. This usually consists of simply
adding the number of bytes pushed as arguments to the stack
pointer.
When the called function executes, the first thing usually done
is to push any registers which must be preserved, and to reserve
space on the stack for any local variables which are required. In
some implementations, a "base" register may also be established to
provide a stable reference to the local variables and arguments.
It is the responsibility of the called function to remove any
saved registers and local variable space from the stack before it
returns. If a value is to be returned to the calling program, it
is expected to be in the ACCUMULATOR register.
MICRO-C Page: 22
Local variables in a function may be referenced as direct
offsets from the "base" register or stack pointer. Note that if
the stack pointer is used, offsets must be adjusted for the number
of bytes which are pushed and popped on the stack during the
execution of the function.
The address of a particular local variable is calculated as:
"base register"
-
(Size of all local variables in bytes)
+
(size of all preceeding local variables in bytes)
-- OR --
"stack pointer"
+
(# bytes pushed during function execution)
+
(size of all preceeding local variables in bytes)
Arguments to a function may also be referenced as direct
offsets from the "base" register or stack pointer, in much the
same way as local variables are.
The address of a particular argument is calculated as:
"base register"
+
(# bytes pushed at entry of function to preserve registers etc.)
+
(Size of return address on stack (usually 2))
+
(# arguments from LAST argument) * 2
-- OR --
"stack pointer"
+
(# bytes pushed during function execution)
+
(size of all local variables in bytes)
+
(# bytes pushed at entry of function to preserve registers etc.)
+
(Size of return address on stack (usually 2))
+
(# arguments from LAST argument) * 2
NOTE: The (number of bytes pushed at entry of function) is a
function of the code generator, and depends on the particular
MICRO-C implementation. Examine some assembly output from the
compiler to determine the actual number on your system.
MICRO-C Page: 23
If a function has been declared as "register", MICRO-C will
load the accumulator with the number of arguments which were
passed, each time the function is called. This allows the function
to determine the location of the first argument.
The address of the first argument passed to a "register"
function may be calculated as:
(accumulator contents) * 2
+
"base register"
+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -