Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pushing a pointer into the eax and ebx registers in GCC

I need to push a pointer into the eax and another into the ebx register. I first solved this with:

register int eax asm("eax");
register int ebx asm("ebx");
int main()
{
     eax = ptr1;
     ebx = ptr2;
}

Which worked like a charm. However, when I added this into my other code, I got some strange errors about gcc being unable to find a register to spill in class AREG, in totally unrelated part of the code. I googled, and it turns out to actually be a bug in gcc -.-. So, I need an other way, to push two pointers, into the eax and ebx registers. Anyone any ideas?

Edit:

Since people have been asking what I am trying to accomplish here, I thought I'd explain a bit.

I need to change the eax and ebx for some assembly code I'm trying to run in my program. I need to execute this assembly code, and give a pointer to the parameter via the eax and ebx register. I execute the assembly code by pushing a pointer to it in ebx and that call ebx. When I don't call the register stuff globally, but locally, the assembly code crashes. If I call it globally, I get this weird error at the end of a random function. When I remove that functions, it throws the same error at another random function. Until I ran out of functions, then it works, but then I miss the rest of the code :P

like image 537
Noah Goldsmid Avatar asked May 25 '13 15:05

Noah Goldsmid


People also ask

WHAT IS EBX in register?

EBX,BX,BH,BL : Called the Base register It is used as a base pointer for memory access Gets some interrupt return values ECX,CX,CH,CL : Called the Counter register It is used as a loop counter and for shifts Gets some interrupt values EDX,DX,DH,DL : Called the Data register It is used for I/O port access, arithmetic, ...

What does MOV EAX EBX do?

mov [eax], [ebx] would mean "move the contents of the memory location pointed to by ebx to the memory location pointed to be eax . That is a memory-to-memory move, which Intel does not support. Note that while general memory-to-memory moves are not supported, some special cases (such as push m32 ) are supported.

What is push RBX?

Saving Registers with Push and Pop You can use push and pop to save registers at the start and end of your function. For example, "rbx" is a preserved register, so you need to save its value before you can use it: push rbx ; save old copy of this register.

What is EAX register?

EAX register, a 32-bit processor register of x86 CPUs. Environmental Audio Extensions, a number of digital signal processing presets for audio, found in Sound Blaster sound cards.


2 Answers

If you have (inline) assembly code that requires specific parameters in EAX/EBX, the way to do this in gcc is to use the following:

__asm__("transmogrify %0, %1\n" : "+a"(val_for_eax), "+b"(val_for_ebx));

This uses what gcc calls inline assembly constraints which tell the compiler that the assembly code - whatever it is - expects val_for_eax/val_for_ebx in EAX/EBX (that's the a/b part) as well as that it will return potentially modified versions of these variables (that's the +) in these registers as well.

Beyond that, the actual code within the asm() statement doesn't matter to the compiler - it'll only need/want to know where the parameters %0 and %1 live. The above example will, due to a transmogrify instruction not existing in the current x86 instruction set, fail when the assembler runs; just substitute it with something valid.

The explanations why gcc behaves this way and exactly what you can tell it to do is in the GCC manual, at:

  • Extended Assembly - Assembler Instructions with C operands
  • Constraints for asm operands, in particular the Intel/386 section of the Machine-specific Constraints list for what to say if you need to pass/retrieve a value in a specific register, and the Modifiers section about the meaning of things like the + (to both pass and return a value; there are other such "modifiers" to the constraints)

You can specify a specific register for a variable but due to the way gcc works / the way inline assembly is implemented in gcc, doing so does not mean (!) the register is from then on reserved (out of scope) for gcc to use for its own purposes. That can only be achieved through constraints, for a specific, single asm() block - the constraints tells gcc what to write into those registers before the placement of the actual assembly code, and what to read from them afterwards.

like image 165
FrankH. Avatar answered Sep 18 '22 12:09

FrankH.


Since the eax register is need all over the place in a valid program on your architecture, your strategy can't work with global variables that are bound to the specific registers. Don't do that, reserving a register globally is not a good idea.

Place the variables that are bound to registers in the particular function, as close as possible to their use.

like image 25
Jens Gustedt Avatar answered Sep 20 '22 12:09

Jens Gustedt