Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading a register value into a C variable [duplicate]

I remember seeing a way to use extended gcc inline assembly to read a register value and store it into a C variable.

I cannot though for the life of me remember how to form the asm statement.

like image 696
Brian Avatar asked Jan 22 '10 00:01

Brian


People also ask

What is register variable in C?

CProgrammingServer Side Programming. Register variables tell the compiler to store the variable in CPU register instead of memory. Frequently used variables are kept in registers and they have faster accessibility.

Can we access the address of a register value?

No, you can't take the address of a variable declared register. It tells the compiler to try to use a CPU register, instead of RAM, to store the variable. Registers are in the CPU and much faster to access than RAM. But it's only a suggestion to the compiler, and it may not follow through.

What is the major difference between the variables of a programming language and registers?

One major difference between the variables of a programming language and registers is the limited number of registers, typically 32 on current computers, like MIPS.


1 Answers

Editor's note: this way of using a local register-asm variable is now documented by GCC as "not supported". It still usually happens to work on GCC, but breaks with clang. (This wording in the documentation was added after this answer was posted, I think.)

The global fixed-register variable version has a large performance cost for 32-bit x86, which only has 7 GP-integer registers (not counting the stack pointer). This would reduce that to 6. Only consider this if you have a global variable that all of your code uses heavily.


Going in a different direction than other answers so far, since I'm not sure what you want.

GCC Manual § 5.40 Variables in Specified Registers

register int *foo asm ("a5"); 

Here a5 is the name of the register which should be used…

Naturally the register name is cpu-dependent, but this is not a problem, since specific registers are most often useful with explicit assembler instructions (see Extended Asm). Both of these things generally require that you conditionalize your program according to cpu type.

Defining such a register variable does not reserve the register; it remains available for other uses in places where flow control determines the variable's value is not live.

GCC Manual § 3.18 Options for Code Generation Conventions

-ffixed-reg

Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role).

This can replicate Richard's answer in a simpler way,

int main() {     register int i asm("ebx");     return i + 1; } 

although this is rather meaningless, as you have no idea what's in the ebx register.

If you combined these two, compiling this with gcc -ffixed-ebx,

#include <stdio.h> register int counter asm("ebx"); void check(int n) {     if (!(n % 2 && n % 3 && n % 5)) counter++; } int main() {     int i;     counter = 0;     for (i = 1; i <= 100; i++) check(i);     printf("%d Hamming numbers between 1 and 100\n", counter);     return 0; } 

you can ensure that a C variable always uses resides in a register for speedy access and also will not get clobbered by other generated code. (Handily, ebx is callee-save under usual x86 calling conventions, so even if it gets clobbered by calls to other functions compiled without -ffixed-*, it should get restored too.)

On the other hand, this definitely isn't portable, and usually isn't a performance benefit either, as you're restricting the compiler's freedom.

like image 92
ephemient Avatar answered Sep 19 '22 23:09

ephemient