I would also like to suggest that you do not use bit fields. Bit fields are not standard across brands of compilers, and may be non-standard among the same compiler with different versions.
For example, a known brand
declares:
Quote:
Microsoft Specific
The ordering of data declared as bit fields is from low to high bit...
END Microsoft Specific
A different brand may declare it from high to low. There are also restrictions with const's and referencing a bit field. For more, read the "NOTES" section at
https://en.cppreference.com/w/cpp/language/bit_field.
With this in mind, you might think that 'flags_t::carry' is at bit 0, when it might be at bit 63.
If you do continue to use bit fields, use some compiler preprocessor defines to make sure you are using a known compiler (and version) that supports the bit fields as you need them. i.e.: Check that the current compiler (and version) is acceptable to the declaration of bit fields as defined by that compiler (and version).
As for calling an assembly routine to get these values, depending on the calling convention, the compiler will place the parameters passed into registers ultimately destroying the values you wish to preserve. For example, the Microsoft convention for 64-bit
declares:
Code:
The first four arguments are placed onto the registers. That means RCX, RDX, R8, R9 for integer...
For example, the following:
Code:
retrieve_general(&general_storage);
Will destroy (at least) RCX.
With this in mind, one way to do it would be to note that an interrupt will not destroy the register state. If you have a known stack, you could generate an (software) interrupt. Now all you have to do is know the placement of the EFLAGS, EIP, CS, SS, ESP, etc, on the given stack (Note that a software interrupt may be different than a hardware interrupt when placing items on the stack).
There may be other ways to do it--simpler as well as not so simple--but either way, you need to know what processor you are running on, what compiler calling convention is being used, is the address state a flat address or a linear address, as well as possibly a few other items.
To retrieve the register state, I simply invoke a GPF. All registers have the values given at the time of the interrupt. (Doing this, you could easily set a flag to return as normal or process the GPF.) To make it easier, you could use an Illegal Instruction sequence which will invoke a lesser used exception handler, though you will still need some way of knowing (within the handler) if this is a "retrieve all registers" call or an actual illegal instruction. A software interrupt might be better for your needs, depending on the platform you are using.
Ben
-
http://www.fysnet.net/osdesign_book_series.htm