Sharing Header files between C and Assembly (enum support)

OP (Company: Universiti Sains Malaysia) #1447759
Rate this post
useful
not useful
Hi,

I'm interested in (re)writing a bunch of drivers for a project in 
assembly, which will be called from C routines. The Compiler and 
Assembler are GNU gcc and as.

I plan to run the Assembly language files through the C pre-processor 
before actual assembly, so that a single header file can be shared 
between the assembly driver routines and the C interface to the routine.

However, I'm having a problem trying to find a good and clean approach 
for dealing with enums. Is there a way to define enums such that they 
can be referenced correctly in both Assembly and C, without duplicating 
it manually like in the following code fragment.
1
#ifndef __ASSEMBLY___ 
2
typedef enum { ENUM_A, ENUM_B, ... } enumvalues;
3
#else 
4

5
#define ENUM_A 0
6
#define ENUM_B 1
7
...
8

9
#endif

TIA
Moderator #1448019
Rate this post
useful
not useful
No, there's no better way than that.  enums are a C language construct,
so they cannot be handled by an assembler.

I hacked a short Perl script that can automatically extract all enum
values from the stabs debugging information (-gstabs) of your object
file(s) (including the final ELF file), and return it as a sequence
of #define statements.  So you could use that to construct an
assembler-only include file supplying #define macros that match the
C file's enum values.
Attached files:
Guest #1448349
Rate this post
useful
not useful
Perhaps something like this?
1
#ifdef __ASSEMBLY__
2
#define BEGIN_ENUM
3
#define ENUM_VAL(name, value) .equ name, value
4
#define END_ENUM(enum_name)
5
#else
6
#define BEGIN_ENUM typedef enum {
7
#define ENUM_VAL(name, value) name = value,
8
#define END_ENUM(enum_name) } enum_name;
9
#endif
10

11

12
BEGIN_ENUM
13
ENUM_VAL(A, 0)
14
ENUM_VAL(B, 1)
15
END_ENUM(foo)
Guest #1449573
Rate this post
useful
not useful
Yes...on second thought I'd think twice before using my approach because 
it leaves you no choice but to assign every value manually.

Personally before I go and parse debug information to generate code I'd 
probably rather invent an own small DSL (using an existing scripting 
language, of course) and use that to define my data and have the C 
headers and the assembly source generated from it.
Guest #1449857
Rate this post
useful
not useful
This is fun. Here's a version that doesn't require you to assign the 
values manually. You could easily extend this to provide full C enum 
support where the values optionally may be assigned.

1
#ifdef __ASSEMBLY__
2
#define BEGIN_ENUM .set last_enum_value, 0
3
.macro enum_val name
4
.equiv \name, last_enum_value
5
.set last_enum_value, last_enum_value + 1
6
.endm
7
#define END_ENUM(name)
8
#define ENUM_VAL(name) enum_val name
9
#else
10
#define BEGIN_ENUM typedef enum {
11
#define END_ENUM(name) } name;
12
#define ENUM_VAL(name) name,
13
#endif
14

15
BEGIN_ENUM
16
ENUM_VAL(A)
17
ENUM_VAL(B)
18
ENUM_VAL(C)
19
END_ENUM(foo)
OP (Company: Universiti Sains Malaysia) #1451375
Rate this post
useful
not useful
I've combined the two versions (to include assignment of values to 
enums), and renamed BEGIN_ENUM/END_ENUM to ENUM_BEGIN/ENUM_END for 
aesthetic reasons. In addition, I've put the macro definition outside of 
the #define ENUM_BEGIN since I'm not sure what happens if multiple 
ENUM_BEGINs are used (where the macro definition would be repeated).

Posted here for easy 'cut-n-paste'
1
#ifdef __ASSEMBLY__
2

3

4
  .set last_enum_value, 0
5
  .macro enum_val name
6
  .equiv \name, last_enum_value
7
  .set last_enum_value, last_enum_value + 1
8
  .endm
9

10
#define ENUM_BEGIN  .set last_enum_value, 0
11

12
#define ENUM_VAL(name) enum_val name
13
#define ENUM_VALASSIGN(name, value)            \
14
  .set last_enum_value, value                 ;\
15
  enum_val name
16
#define ENUM_END(enum_name)
17

18
#else
19

20
#define ENUM_BEGIN typedef enum {
21
#define ENUM_VAL(name) name,
22
#define ENUM_VALASSIGN(name, value) name = value,
23
#define ENUM_END(enum_name) } enum_name;
24

25
#endif
Moderator #1451519
Rate this post
useful
not useful
Bartli wrote:
> Cool. I actually didn't know you could use semicolons as line breaking
> character in gas, ...

It's processor-dependent.  IIRC, the AVR uses semicolons as a comment
delimiter, and then offers dollar signs as alternate line breaking
characters instead.

Reply

Please log in before posting.

or

Log in with Google account

Registration is free and takes only a minute.

Register now