I declare 32 bit variables in the MyAsmVar section.
I know the base address of MyAsmVar. Also I know the address of var1 and var2.
AREA MyAsmVar, DATA,NOINIT, READWRITE, ALIGN=3
var1 DCD 0x00 var2 DCD 0x00
LDR R0,=0x20000000 ; base address of MyAsmVar LDR R1,[R0,#0] ; read var1 in to R1 (var1 address is 0) LDR R2,[R0,#4] ; read var2 in to R2 (var2 address is 4)
We must know the numeric value of variable address and this is not good.
How can I use the variables names instead of address?
I want the following lines but compiler give error messages;
LDR R0,=0x20000000 LDR R1,[R0,#var1] ; read var1 in to R1 LDR R2,[R0,#var2] ; read var1 in to R2
Also i try following lines but compiler dont compile.
LDR R1,[R0,#&var1] ; read var1 in to R1 LDR R2,[R0,#&var2] ; read var1 in to R2
if I use
var1 equ 0 var2 equ 4
problem solving, but i dont want to count address of variables.
What makes you think that you can beat the compiler at this?
Okey i am writing again.
var1 and var2 are 32 bit variables. I can easly learn the values of this variables if i know the var1 and var2 address.
for example
var1 variable's address is 0x20000000. var2 variable's address is 0x20000004.
Base_Addr=0x20000000
var1 relative address is 0 var2 relative address is 4
LDR R0,=0x20000000 LDR R1,[R0,#0] LDR R2,[R0,#4]
or
i can define
val1 equ 0x00 val2 equ 0x04
and after
LDR R0,=0x20000000 LDR R1,[R0,#val1] LDR R2,[R0,#val2]
Ok?
These are not problem.
if i dont know the var1 and var2 address what can i do?
Base address is 0x20000000
varx dcb 0x00 vary dcb 0x00 ... ... ... var1 dcd 0x00 var2 dcd 0x00
Compiler give error message for #var1 and #var2
Ok i may be wrong write it. There for compiler give error messages.
what is the true form? (You say it)
I need simple directive name but i dont know it.
For example you say to me "use LDR R1,[R0,#AdrOf(val1)]"
Thats all....
"what is the true form? (You say it)"
There is no one true form. I have already given you a workable alternative.
If code size is important, then you might well be better off looking at the thumb instruction set.
If you REALLY want to do it your way then you could have a series of equates, something like:
. . . VarBase ;Base address for the following variables Var1 dcb 0 ;Variable #1 Var2 dcb 0 ;Variable #2 OFFSET_VAR1 set Var1-VarBase ;Offset from VarBase for Var1 OFFSET_VAR2 set Var2-VarBase ;Offset from VarBase for Var2 . . . LDR R0,=VarBase ;Set R0 to base address of variable block LDR R1,[R0,#OFFSET_VAR1] ; LDR R2,[R0,#OFFSET_VAR2]
WARNING: This code block is intended to illustrate a possible method. It is not complete and may have syntax errors.
Ok i am giving simple C example.
int a,b,c;
int main() { a=1; b=2; c=3; }
Select optimization level 0 and compile it.
You will see following asm codes in the debug menu.
5: a=1; 0x000001C8 2001 MOVS r0,#0x01 0x000001CA 4905 LDR r1,[pc,#20] ; @0x000001E0 0x000001CC 6008 STR r0,[r1,#0x00] 6: b=2; 0x000001CE 2002 MOVS r0,#0x02 0x000001D0 4904 LDR r1,[pc,#16] ; @0x000001E4 0x000001D2 6008 STR r0,[r1,#0x00] 7: c=3; 0x000001D4 2003 MOVS r0,#0x03 0x000001D6 4904 LDR r1,[pc,#16] ; @0x000001E8 0x000001D8 6008 STR r0,[r1,#0x00]
This code same as your suggested codes.
------------------------------------------------
Now select optimization level 3 and recompile it.
5: a=1; 0x000001C8 4804 LDR r0,[pc,#16] ; @0x000001DC 0x000001CA 2101 MOVS r1,#0x01 6: b=2; 0x000001CC 6001 STR r1,[r0,#0x00] 0x000001CE 2102 MOVS r1,#0x02 7: c=3; 0x000001D0 6041 STR r1,[r0,#0x04] 0x000001D2 2103 MOVS r1,#0x03 8: } 0x000001D4 6081 STR r1,[r0,#0x08]
This codes same as my need codes.
You see C compiler solve this problem. But we can't do by assembler.
How I can do?
Of course you can - and you also got one example how to do it.
The difference between assembler and C is that with assembler, you have to do all the extra work that the compiler does on its own.
It's up to you to declare three individual variables, or to just allocate storage large enough for three variables and then play with the individual offsets. Or to try to do the IB Shy workaround, writing extra assembler lines to compute the offsets.
Other cpu's compilers has $ or offset type asm directives. But i didnt find in the keil.
I can't solve this problem If i don't find the address learning directives.
"But we can't do by assembler."
Didn't my suggested method do the same thing?
If you really want it, you could do it. As I said before:
"You could of course write a simple macro."
@IB Shy, i said "Which asm directive gives to me address of the variable, i dont know."
Therefore i cant write the macro.
Can you write?
"I can't solve this problem"
So why don't you just write in 'C', then?!
How long do you think it is going to take you to become sufficiently profficient at ARM Assembler for you to be able to outsmart the compiler?
If you really need to become an expert ARM Assembly programmer - which you will need to be in order to outsmart the compiler - then I would suggest taking a training course...
"Which asm directive gives to me address of the variable, i dont know."
Part of my example loaded R0 with the address of VarBase.
Part of my example set a variable to determine the offset of a variable from a reference point.
So, there you are. All the information you need.
"Can you write?
Yes, and please don't ask for an example - I've already given you the starting point for one.
VarBase ;Base address for the following variables Var1 dcb 0 ;Variable #1 Var2 dcb 0 ;Variable #2 OFFSET_VAR1 set Var1-VarBase ;Offset from VarBase for Var1 OFFSET_VAR2 set Var2-VarBase ;Offset from VarBase for Var2
.
Is starting point this codes?
OFFSET_VAR1 set Var1-VarBase ;Offset from VarBase for Var1
we don't know the numeric value of address of Var1
Therefore you cant write the this line "OFFSET_VAR1 set Var1-VarBase"
But you can write following codes
Var1 dcb 0 ;Variable #1 Var2 dcb 0 ;Variable #2 Var3 dcw 0 ;Variable #3 Var4 dcd 0 ;Variable #4 Var5 dcd 0 ;Variable #5 and OFFSET_VAR1 equ 0 OFFSET_VAR2 equ 1 OFFSET_VAR3 equ 2 OFFSET_VAR4 equ 4 OFFSET_VAR5 equ 8
I dont use this lines because i dont want to count "which variable where"
"we don't know the numeric value of address of Var1"
I gave you the basic idea. I've just done very little reading of the Keil documentation and confirmed that the idea is fundamentally correct. I've looked at some source code included with the Keil distribution and it does the same sort of thing.
Sorry, but if you're wanting to be spoon fed, you had better find someone else.
I use 32K limitted version of Keil. (This is may be problem.)
--- I try this ---
LDR R1,[R0,#Var1]; Keil give error mesage:
Startup.s(163): error: A1110E: Expected constant expression Startup.s: 163 00000100 LDR R0,[r1,#var1] Startup.s: ^ Startup.s: 1 Error, 0 Warnings
LDR R1,[R0,#$Var1]; Keil give error mesage:
Startup.s(163): error: A1169E: Missing close square bracket Startup.s: 163 00000100 LDR R0,[r1,#$var1] Startup.s: ^ Startup.s: 1 Error, 0 Warnings
Var1 dcb 0 ;Variable #1 OFFSET_VAR1 set Var1-0x20000000 ;Offset from VarBase for Var1 LDR R0,=VarBase ;Set R0 to base address of variable block LDR R1,[R0,#OFFSET_VAR1] ;
Startup.s(66): error: A1163E: Unknown opcode set , expecting opcode or Macro Startup.s: 66 00000004 OFFSET_VAR1 set var1-0x20000000 Startup.s: ^ Startup.s: 1 Error, 0 Warnings
I didnt find how can i solve this problem in the Keil. (Also i tried the GBLA directive.)
But if i cant find the answer i will write precompiler program.
I write following asm codes
Var1 DCD 0x00; Var2 DCD 0x00; Var3 DCD 0x00; Var4 DCD 0x00;
LDR R0,=0x20000000 LDR R1,[R0,#ADRVar1] LDR R2,[R0,#ADRVar2] LDR R3,[R0,#ADRVar3] LDR R4,[R0,#ADRVar4]
Here we dont have the ADRValx values. My program automaticaly calculate the address of varaibles and inserts the following lines in to orginal asm source.
ADRVar1 equ 0x000 ADRVar2 equ 0x004 ADRVar3 equ 0x008 ADRVar4 equ 0x00C
Now Keil easyly compiles my codes.
But i think i do not know to small trick. Because this basic problem must be solve by keil asm compiler.
MDK-ARM Evaluation Tools
Programs that generate more than 32 Kbytes of code and data will not compile, assemble, or link.
The debugger supports programs that are 32 Kbytes or smaller. The compiler does not generate a disassembly listing of the machine code generated. The -S, --asm, and --interleave compiler command-line options are disabled.
The compiler and assembler do not generate position-independent code or data. The --apcs /ropi /rwpi /pic/ pid compiler and assembler command line options are disabled.
The assembler and linker create Symbolic Output Format objects which cannot be linked with third-party linker utilities. Fully licensed tools generate standard ELF/DWARF files which may be used with third-party utilities.
The linker does not accept scatter-loading description files for sophisticated memory layouts. The --scatter command line option is disabled.
The base address for the code and constants in memory must be 0x000080000, 0x000100000, 0x000200000, 0x000300000, 0x000400000, 0x010400000, 0xXX000000, or 0xXX800000 (where XX is a Hexadecimal number from 00-FF). When the base address is 0x0 the linker places the code at the start of on-chip Flash of most ARM processor-based microcontrollers.
Is the my problem is linked to text bold? (I use uvision V1.14.4)
"I use 32K limitted version of Keil. (This is may be problem.)"
Not the problem.
"Is the my problem is linked to text bold? (I use uvision V1.14.4)."
Why do you try to find a very complicated reason? It's not complicated.
Sorry, but I think I have already given you something very close to the answer already and I'm not going to give any more. If you can't find the solution for such a simple problem yourself, maybe you should consider just doing whatever you're trying to do in C.
Absolutely!
Again, to outperform the compiler will require you to be very good at ARM Assembler. That is clearly not the case, so you have to choices:
1. spend some serious time doing some serious study of ARM assembler;
2. let the compiler to it.
If you really want to go for option 1, then I would recommend a taught class; but, at least, you will need some books: http://www.keil.com/books/armbooks.asp