Maybe. But they would not nearly be as fast, nor as code efficient.A proficient C programmer might have written the library functions with a level of scope or encapsulation that might have eliminated the need for many ad hoc global flags.
Maybe. But they would not nearly be as fast, nor as code efficient.A proficient C programmer might have written the library functions with a level of scope or encapsulation that might have eliminated the need for many ad hoc global flags.
True, that's why some ASM is used in Linux. When the tradeoffs of HLL structure exceeds the absolute requirement for speed and efficiency it is used but it's not very often outside of the hardware bit banging needed in drivers or chip level boot code.Maybe. But they would not nearly be as fast, nor as code efficient.
Yup. And, again, I am not writing kernels, and I don't have essentially infinite RAM, ROM, and instructions cycles.True, that's why some ASM is used in Linux. When the tradeoffs of HLL structure exceeds the absolute requirement for speed and efficiency it is used but it's not very often outside of the hardware bit banging needed in drivers or chip level boot code.
Yes, that is what I thought. This just reinforces my belief that C has no place for coding small embedded processors.
If wanting to write code with as few bytes as possible is your primary concern, then by all means, assembly language is the way you should go.
And this would be my continued preference, as it has been for nearly 40! years.If wanting to write code with as few bytes as possible is your primary concern, then by all means, assembly language is the way you should go.
Done.BTW, my LED blinky code is 2 instructions long:
[...]
I'd love to see the C code that resolves into these 2, and only 2, instructions.
asm("btsfc tc256ms; btg led");
Excellent. In your example, how are tc256ms and led defined, such that they are accessible* to both the C and .asm code?Done.
Any questions?Code:asm("btsfc tc256ms; btg led");![]()
#define tc256ms tmrchg,0,0 ;bit 0 of tmrchg register
#define led latc,0,0 ;bit 0 of latc register
Well, which variables need to be visible from each environment? The basic pattern for the two use cases would be something like...Excellent. In your example, how are tc256ms and led defined, such that they are accessible* to both the C and .asm code?
/*
These should appear at global scope (not within any function)
*/
volatile short foo = 1024;
asm("EXTERN foo");
/*
These should appear at global scope (not within any function)
*/
extern short foo;
asm("foo res 2");
asm("GLOBAL foo");
Yeah...Well, which variables need to be visible from each environment? The basic pattern for the two use cases would be something like...
To access a C variable from ASM:
To access an ASM variable from C:Code:/* These should appear at global scope (not within any function) */ volatile short foo = 1024; asm("EXTERN foo");
EDIT: changed "int" to "short".Code:/* These should appear at global scope (not within any function) */ extern short foo; asm("foo res 2"); asm("GLOBAL foo");
You want Boolean flags if I do understand you correct when using xc8With the demise and continued aging of MPLab (in favor of X), I am considering porting some of my .asm libraries to XC8. But I've got a dilemma:
Each of my libraries has a set of library-dependent global flags (boolean bits) that are packed into flag bytes. In assembly, I do this in a .inc file. The register location and position of the bits are irrelevant, and tracked by the label. For example:
I do this manually, and pack all of the required bits into the fewest number of registers as possible.Code:#define pwrup flag0,0,0 ;0=normal/1=powering up #define minboot flag0,1,0 ;0=normal/1=minboot #define shtdwn flag0,2,0 ;1=Shutdown system #define fsleep flag0,3,0 ;0=Normal Operation/1=go to sleep #define update flag0,4,0 ;1=update display #define fbcolon flag0,5,0 ;1=blink colon when clock runs #define fcold flag0,6,0 ;1=temp too cold #define fhot flag0,7,0 ;1=temp too hot #define bdead flag1,0,0 ;1=Battery dead #define _adrdy flag1,1,0 ;1=On-chip A/D conversion ready #define run flag1,2,0 ;0=warmup/1=run #define lbpdf flag1,3,0 ;low battery power down flag #define _spst flag1,5,0 ;0=speaker lo, 1=speaker hi #define ftest flag1,6,0 ;0=normal, 1=test mode #define fsecond flag1,7,0 ;1=1 second elapsed
I could likely do something similar in C:
But I would need to define my globals on a project (as opposed to library) basis -- depending upon the libraries I wanted to use -- and pack the bits manually into one struct per flag register, with each flag register possibly spanning multiple libraries. This is sub-optimal.C:struct { unsigned pwrup :1; //0=normal/1=powering up unsigned minboot :1; //0=normal/1=minboot unsigned shtdwn :1; //1=Shutdown system unsigned fsleep :1; //0=Normal Operation/1=go to sleep unsigned update :1; //1=update display unsigned fbcolon :1; //1=blink colon when clock runs unsigned fcold :1; //1=temp too cold unsigned fhot :1; //1=temp too hot } flag0;
Is there a way to define global bits in XC8 in the library header files so that they are automatically packed into the smallest possible number of compiler-allocated global bytes?
Interestingly, this is easy to do in Pascal (using sets). Can C do it?
I am not familiar with the stdbool.h library. Does it pack multiple bits (flags) into a single register or give each flag its own register?You want Boolean flags if I do understand you correct when using xc8
in your .H file
#include <stdbool.h>
bool run_this_thing;
bool Stop;
// or
struct
{
int Beep_Count;
int Beep_Int;
int Beep_Time;
int Beeps;
bool Silent; //<<<<<<<<<<<<
}Beep_Gen;
Picbuster
Nope, just imports a few C++ boolean-related constructs into a C program. Something along the lines of:I am not familiar with the stdbool.h library. Does it pack multiple bits (flags) into a single register or give each flag its own register?
typedef unsigned char bool;
#define false 0
#define true 1
This thread is not really about running asm code, it's about data structures and how you move from the hardware machine level structures of registers/bits to abstract HLL data structures in an efficient and logical manner. C is a general language that leaves details like packing and padding to the implementation on each machine type for the C abstract machine registers. Obviously this is necessary because each machines architecture is different in the way it can efficiently handle registers and bits. When you actually need hardware machine level control of the C registers/bits layout (like in my example above using rs232 data transfers) there are options to manipulate them from the default to just about any format. However, there are limits. What might be efficient and logical data structures in a ASM context dealing directly with hardware registers might not be efficient and logical data structures in a pure C context to those same hardware registers and trying to force that structure detracts from the ability of C to possibly eliminate the need for flat low level global implementations of data in the first place.There is a reason 'C' is considered the high-level assembler. There are very few things it cannot do as well as, or almost as well as assembler, because it was written for that purpose. Maximum responsibility, maximum freedom.
So far, I haven't seen anyone discussing (in this thread) simply handcoding assembly language, stuffing it into a C variable, and then calling it with a function pointer (you have to manage the stack-frame and registers, but this is a stub on either end of the called assembly code, and is not difficult). This simply eliminates the inability of a compiler to support inline assembly.
And as you ponder this thought, consider my objective: the tightest, fastest possible code....detracts from the ability of C to possibly eliminate the need for flat low level global implementations of data in the first place.
It's unlikely you will get that with C but what you will get with good C code is something another person can read and understand quickly if you are hit by a meteor while in the swimming pool.And as you ponder this thought, consider my objective: the tightest, fastest possible code.
Actually, my commercial .asm code is laid out pretty damn well, in a very organized fashion, and is pretty easy to maintain.It's unlikely you will get that with C but what you will get with good C code is something another person can read and understand quickly if you are hit by a meteor while in the swimming pool.