In ASM51, the following code is every useful:
-------- file1.asm --------- public MAX MAX EQU 10 -------- file2.asm --------- extrn number(MAX) MOV A,#MAX
-------- file2.C ----------- extern code MAX; #define MAX_NUMBER ((unsigned char)&MAX)
I think you're looking at the wrong type of "constant" on the C side of that problem. C preprocessor macros are absolutely and strictly local to each source file. They're gone completely before the code even reaches the main compiler, let alone anything gets written into any object file. In this respect, C macros are completely different than what you're used to find in macro assemblers. C doesn't really have the concept of a symbolic constant, certainly none that could be linked in from another, separately compiled source file. OTOH: why insist on having all this work done by the linker? A simple shared #include file containing a line like
#define MAX 10
One year has passed but nobody give me a good answer. I insist on "linking" the constant, because I am generating a LIB file, whose internal configuration constants should be defined by user. So, can any one give me better answer?
The usual way to do this in C would be to supply a header file with some definitions: config.h extern U8 const myVal; and tell users of the library that they need to create an object file that defines values for those constants. config.c: U8 const myVal = 99; You then link config.o with the rest of your library. Typically, use of myVal will generate code that loads myVal from some address (determined by the linker) -- something like (at a guess) ; small model MOV R0,#myVal MOV A,@R0 ; large model MOV DPTR,#myVal MOVX A,@DPTR This code will be larger than code that loads a value as an immediate value. That is, the value is included literally in the instruction, not by reference. MOV A,#99 If this difference is important to you, then life will be a little more painful. When the assembler runs, it actually generates code like this: 0100: MOV A,#00 along with an entry in the object file that says "label MAX is at address 101". The linker then replaces the byte at address 101 with the value defined for MAX. There is no way to write C code with a "placeholder" value such as the EXTERN NUMBER in the assembler. (Such syntax would have to look something like: U16 myMax = ???; where "???" is the value to be replaced by the linker. So, there's no way to write C to get that "to be determined" integer. There is a way to cheat, though. It's easy to write C code that generates addresses that get patched up by the linker. And you can cast an address. So, you could write C thus: extern U8 MAX; // type doesn't really matter U16 myMax = (U16)&MAX; Now, all you have to do is tell your linker the address of MAX. It will find all references to the address-of-MAX in the object files and fix them up, thus replacing the value in line, as desired. I find this technique "painful" because on the one hand, it's not really obvious what you're doing. It obscures the real type and purpose of MAX. And every linker has its own idiosyncratic way of defining symbols, so it's a really non-portable technique. Unless the few extra bytes of code are really going to cripple your application, you might want to just use the first method. Yet another method would be to distribute source code (obfuscated, perhaps, if piracy is a concern), put the definitions in a common header file, and have the user recompile the whole works.
One year has passed but nobody give me a good answer. ... That same year also passed without any feedback from you about the answers you did get. If you didn't consider those "good" answers, why wait all of a whole year to say so? Are you actually trying to make us believe it never occured to you that the reason none of the answers were to your liking might have been that the trick you're trying to pull is impossible? Even in the ligth of some of your answers telling you exactly that?
Hi, I have the following line in my assembly code and I want to link with C program. How to declare in C? EXTRN NUMBER (RS485_TASK, RECV_END) Thanks in advance.
"One year has passed but nobody give me a good answer." Well, I'm sorry - I didn't realise I was supposed to drop everything and concentrate on your problem! Anyway, think about what the Linker does: it deals with addresses - you define a symbol in 'C', and the Linker fixes its address. Therefore, if you want the Linker to give a constant back to 'C', it will be as the address of a 'C' symbol. Your 'C' code will have to take the address of the symbol, and interpret that address value as the required constant (probably via a cast).
Dear Hans-Bernhard Broeker, and all those who concern my question, Actually, I know all the ways everybody have mentioned. And I have tried even more. At last I found that the problem lies in the optimization defects of Keil. Let me expain in detail. Define in a configuration asm:
MAX equ 10 public MAX
extern unsigned char MAX[1];
uint8 Test(uint8 i) { if(i == (uint8)MAX) return 1; return 0; }
uint8 Test(uint8 i) { if(i == (uint8)MAX) return (uint8)MAX; return 0; }
extern code uint8 MAX
You don't give any real explanation why the differences in behaviour of the code for these two particular functions would constitute an optimizer defect. C51 functions aren't reentrant unless you ask for them to be. That has nothing to do with the subject of this thread.
View all questions in Keil forum