This line:
thresBits = _crol_(thresBits, 2);
generates this SRC:
MOV R7,thresBits?1282 MOV R0,#02H MOV A,R7 INC R0 SJMP ?C0198 ?C0197: RL A ?C0198: DJNZ R0,?C0197 MOV thresBits?1282,A
I have added a "#pragma asm" to manually change the assembly to this:
#pragma asm MOV A, thresBits RL A ;rotate once RL A ;rotate the 2nd time MOV thresBits, A #pragma endasm
but I get "error A45: UNDEFINED SYMBOL". How do I access the local C thresBits variable in my inline assembly code?
Did you try: thresBits = thresBits << 2;
Otherwise you may need an underscore. Assuming the Compiler did not use a register for thresBits.
Thanks Neil,
thresBits = thresBits << 2;
would work great if I needed to shift.
I need to rotate the bits by 2, so I would need to do this:
thresBits = (thresBits << 2) | (thresBits >> 6);
which is more inefficient!
What does the code generator actually name the variable? From the posted snippets, it looks like "thresBits?1282" rather than "thresBits".
The segment naming convention is easy to find. I wasn't so successful with a casual search at finding the naming convention for individual objects.
OK, great.
Adding the ?1282 works. This number is now ?1289 however. Does this mean I will have to periodically update the number when if I change my variables or their order?
"Does this mean I will have to periodically update the number when if I change my variables or their order?"
Yes - in fact, you will have to check it every single time you recompile.
That's why it would be better to do this in a proper assembler module, IMO...
Sharing data with another module would usually involve a global variable (which you would import into assembler with EXTERN) or a parameter. thresBits is presumably a local variable, so I doubt EXTERN can grab it.
It would be slightly more expensive to marshal thresBits into a parameter (R7)
thresBits = mycrol (thresBits); -- ; U8 mycrol (U8 in) _mycrol: MOV A, R7 RL A RL A MOV R7,A RET
but at least you won't have the hassle of updating the variable name every time the overlay analysis or code changes move it.
IMO, Keil doesn't really support true inline assembly, for this among other reasons. Of course, it's a valid argument as to whether or not you even want to support true inline assembly, since it will always depend on variablequirks of the code generator -- and not all such bugs will be this easy to find.
IMO, Keil doesn't really support true inline assembly .... and now that it ended up as a subroutine, why not put it in a a51 module?
Erik
Why do something simple, when something advanced can be done?
Write a SED or AWK script that scans through the map file, or assembler list files and extracts the little magic digits and then patch the source file with the correct variable name and rebuild again :)
Thanks for your answers guys. I did consider pushing that snippet into a function, but if I did that, I think the code would take about as long as the library code.
I've ended up reverting to the library code, as it's a bit more of a hassle to debug using the SRC file.
My request wasn't so much of a necessity as a inquiry into what was possible with Keil and inline assembly, and also how to go about it.
That line of code is part of a loop in a much larger time-critical function, but I've optimised other parts such that the difference between compiler generated code and my assembly didn't really matter for that particular line.
If made a function, it would be almost as large as the existing function, but it would be faster since it is hard-coded for a two-step rotate and doesn't need the loop.
What is your problem - the size or the speed of the existing function?
That line of code is part of a loop in a much larger time-critical function why not write the entire loop in assembler - that will do it. My projects are 80 - 100 percent C depending on the amount of time critical stuff.
Regarding the function, my thought was the overhead added by a function call would negate the speed increase from using assembly since it's such a small routine.
I did consider rewriting the loop in assembly. I felt my time was better spent elsewhere in the program, as my task list is still fairly long. My assembly isn't that hot either.