C and assembly

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
dumaisp
Posts: 13
Joined: Fri Feb 15, 2008 8:58 am

C and assembly

Post by dumaisp »

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?
xyzzy
Member
Member
Posts: 391
Joined: Wed Jul 25, 2007 8:45 am
Libera.chat IRC: aejsmith
Location: London, UK
Contact:

Post by xyzzy »

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
djenkins75
Posts: 11
Joined: Sun Dec 16, 2007 11:32 am
Location: Wisconsin, USA

Post by djenkins75 »

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.
skyking
Member
Member
Posts: 174
Joined: Sun Jan 06, 2008 8:41 am

Post by skyking »

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:

Code: Select all

BEGIN_STRUCT(MyStruct)
DEF_MEMBER(int, x)
DEF_MEMBER(char*, p)
END_STRUCT
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]
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

--- 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.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Watch out for GCC doing silly things with alignment and padding bytes. Remember to specify any shared struct as __attribute__((packed)).
dumaisp
Posts: 13
Joined: Fri Feb 15, 2008 8:58 am

Post by dumaisp »

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
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

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
Until you move to 64-bit ;)
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

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
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).
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

JamesM wrote:Watch out for GCC doing silly things with alignment and padding bytes. Remember to specify any shared struct as __attribute__((packed)).
"silly" ?

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.
Post Reply