C and assembly
C and assembly
Hi,
I am currently using c-style header files with assembly source codes to declare any constants. That way, my C files and asm files can use the same include files without having to redeclare every constant twice.
I am now wondering how I could share a declaration of a structure between my C files and asm files. Right now I have a .h file with the struct declaration and I have a .inc file with constants defining the offsets of members in that struct. I don't like the idea of maintaing two files for the same declaration.
My question is: using GCC4, is there a way to use a C-style declaration of a struct within asm source files?
I mean, it's not that hard for the assembler, it should know that a member of type "int" is 32bit.
if it is impossible, does this mean that If I would have to use C++ classes within asm code, I would have to declare an interface for the class for each languages used?
I am currently using c-style header files with assembly source codes to declare any constants. That way, my C files and asm files can use the same include files without having to redeclare every constant twice.
I am now wondering how I could share a declaration of a structure between my C files and asm files. Right now I have a .h file with the struct declaration and I have a .inc file with constants defining the offsets of members in that struct. I don't like the idea of maintaing two files for the same declaration.
My question is: using GCC4, is there a way to use a C-style declaration of a struct within asm source files?
I mean, it's not that hard for the assembler, it should know that a member of type "int" is 32bit.
if it is impossible, does this mean that If I would have to use C++ classes within asm code, I would have to declare an interface for the class for each languages used?
-
- Member
- Posts: 391
- Joined: Wed Jul 25, 2007 8:45 am
- Libera.chat IRC: aejsmith
- Location: London, UK
- Contact:
I don't think you can use the struct from ASM, but, if you're using GAS, you can at least unify the 2 headers into one. Just pass -D__ASM__ or similar to gcc when compiling the ASM file, then wrap the C-only parts (stuff that isn't #defines, basically) in
Code: Select all
#ifndef __ASM__
...
#endif
-
- Posts: 11
- Joined: Sun Dec 16, 2007 11:32 am
- Location: Wisconsin, USA
You could write a program to convert the ".h" file into an appropriate ".inc" file and integrate it into your build script. Then the ".inc" file becomes an intermediate compilation target and not something that you would typically store in revision control and definitely not hand edit.
If writing a parser for a full blown ".h" file is a bit over the top, you could define your own language and use a tool like perl or m4 to translate it into both the ".h" file and the ".inc" file.
You can use lexx and yacc (or flex and bison for you GNU folks out there). There is also a really good open source parser generator called "lemon". It is part of the sqlite embedded SQL database system (http://www.hwaci.com/sw/lemon/).
I did something like this once for a network game that I wrote. I defined all of my game objects in my own language and wrote a translator to emit C header files, C network / data marshaling code, C struct "object factory" like code. I was working on code to emit code to stream my objects to and from XML for persistent storage, but I got bored and moved on to something else.
Anyway, the technique worked well in theory and practice.
If writing a parser for a full blown ".h" file is a bit over the top, you could define your own language and use a tool like perl or m4 to translate it into both the ".h" file and the ".inc" file.
You can use lexx and yacc (or flex and bison for you GNU folks out there). There is also a really good open source parser generator called "lemon". It is part of the sqlite embedded SQL database system (http://www.hwaci.com/sw/lemon/).
I did something like this once for a network game that I wrote. I defined all of my game objects in my own language and wrote a translator to emit C header files, C network / data marshaling code, C struct "object factory" like code. I was working on code to emit code to stream my objects to and from XML for persistent storage, but I got bored and moved on to something else.
Anyway, the technique worked well in theory and practice.
There are two adequate solutions:
The easy one is similar to what dumaisp wrote, but you define your struct in a separate include file that could expand to both the struct definintion and the code for generating the .inc file depending on macro definitions. The file might look something like:
And your export program would include this twice, once with macro definitions suitable for expanding this into a struct definition and onec with macro definitions suitable for generating the code for emitting macro definitions for the data offsets.
The little harder solution is to modify gcc to emit .inc files directly from whatever struct definitions it comes across or parse the output from gcc when you select to dump this information (RTGM).[/code]
The easy one is similar to what dumaisp wrote, but you define your struct in a separate include file that could expand to both the struct definintion and the code for generating the .inc file depending on macro definitions. The file might look something like:
Code: Select all
BEGIN_STRUCT(MyStruct)
DEF_MEMBER(int, x)
DEF_MEMBER(char*, p)
END_STRUCT
The little harder solution is to modify gcc to emit .inc files directly from whatever struct definitions it comes across or parse the output from gcc when you select to dump this information (RTGM).[/code]
--- Edit --- Well, that's what I get for skimming instead of reading.. my first solution is about the exact same as the one above, but I'll leave it for you're viewing (dis)pleasure.
Well, I don't use ASM structs at all, so I am not really sure. But, you can try using defines to map to the correct type convention in a seperate include (include.h and include.inc). so, for example:
//This would be in your include.h
#define MakeStruct(Name) struct Name {
#define EndStruct };
//This is in your include file for Test_S structure
MakeStruct(Test_S);
int Test;
EndStruct;
Then in your ASM file, you would make a macro that uses the ASM specific syntax for declaring a structure, and a define to make it think a long is a dd, char is a db, short is a dw, etc. Also, make sure you disable alignments in your C compiler, or your structures won't match up properly in some cases.
I am not 100% sure about your asm syntax, but you may also be able to just override the struct word (token) with whatever it's called in ASM, and { with the start token, and } with the end structure token. Then override the variables (int, char, etc) with their correct counterpart, and include regular header files right into your ASM code. It all depends on how much you can do with your ASM compiler . Like I said, I don't use struct's in asm, so I'm not really sure how well it will work, just trying to throw some ideas out there to try.
Well, I don't use ASM structs at all, so I am not really sure. But, you can try using defines to map to the correct type convention in a seperate include (include.h and include.inc). so, for example:
//This would be in your include.h
#define MakeStruct(Name) struct Name {
#define EndStruct };
//This is in your include file for Test_S structure
MakeStruct(Test_S);
int Test;
EndStruct;
Then in your ASM file, you would make a macro that uses the ASM specific syntax for declaring a structure, and a define to make it think a long is a dd, char is a db, short is a dw, etc. Also, make sure you disable alignments in your C compiler, or your structures won't match up properly in some cases.
I am not 100% sure about your asm syntax, but you may also be able to just override the struct word (token) with whatever it's called in ASM, and { with the start token, and } with the end structure token. Then override the variables (int, char, etc) with their correct counterpart, and include regular header files right into your ASM code. It all depends on how much you can do with your ASM compiler . Like I said, I don't use struct's in asm, so I'm not really sure how well it will work, just trying to throw some ideas out there to try.
OK, well unfortunately I see that the way I was doing it seems to be the easiest way. I thought about writing somekind of parser that would generate the proper declarations, but using macros like the solution mentionned above seems to be a good idea. although the overhead of doing this might be the same as writing both declaration with a #ifdef __ASSEMBLER__ ....
As for the padding part, I guess that if I only use 32bit members (i.e: all pointers) gcc won't padd anything? But I will look into that attribute thing.
Thanks a lot for your replies
As for the padding part, I guess that if I only use 32bit members (i.e: all pointers) gcc won't padd anything? But I will look into that attribute thing.
Thanks a lot for your replies
Until you move to 64-bitdumaisp wrote:OK, well unfortunately I see that the way I was doing it seems to be the easiest way. I thought about writing somekind of parser that would generate the proper declarations, but using macros like the solution mentionned above seems to be a good idea. although the overhead of doing this might be the same as writing both declaration with a #ifdef __ASSEMBLER__ ....
As for the padding part, I guess that if I only use 32bit members (i.e: all pointers) gcc won't padd anything? But I will look into that attribute thing.
Thanks a lot for your replies
I typically use #pragma pack(1) and #pragma pack() in my header files that I don't want padding, and I also set the default padding to none when compiling, just incase something was missed. I forget the syntax off the top of my head, but it's like -fpack-struct or some crap, much easier than going back through all your sources, although there may be times when you want padded structs (although, I don't typically let the compiler do my aligning, I tend to pad my structs the way I want them, and reserve space for future needs).dumaisp wrote:OK, well unfortunately I see that the way I was doing it seems to be the easiest way. I thought about writing somekind of parser that would generate the proper declarations, but using macros like the solution mentionned above seems to be a good idea. although the overhead of doing this might be the same as writing both declaration with a #ifdef __ASSEMBLER__ ....
As for the padding part, I guess that if I only use 32bit members (i.e: all pointers) gcc won't padd anything? But I will look into that attribute thing.
Thanks a lot for your replies
"silly" ?JamesM wrote:Watch out for GCC doing silly things with alignment and padding bytes. Remember to specify any shared struct as __attribute__((packed)).
It's trying to get a basic bit of performance out of your wrecked structs. Try ordering them in the following order:
long double
64-bit integers + doubles
pointers
32-bit integers + floats
16-bit integers
8-bit integers + characters
bitfields
That should reduce the amount of padding to a minimum. For clarity, add the padding explicitly to make everything naturally aligned. The previous order requires no padding ever (for 32-bit and 64-bit computers without segments) except perhaps before the bitfields.