Inline assembly : reading a register [SOLVED]

Programming, for all ages and all languages.
Post Reply
remy
Posts: 23
Joined: Thu Nov 20, 2014 4:06 pm

Inline assembly : reading a register [SOLVED]

Post by remy »

I'm trying to do a 64-bit kernel in C on gcc so I need to read from a register in inline assembly.

Here's my attempt :

main.c :

Code: Select all

asm(".intel_syntax noprefix");  //Use of NASM

int main(void){

    clear();

    asm("mov rax, 0x1");    //I try to change the default value of Rax
                            //  which is 0 on Qemu

    long rax;
    rax = readRax();

    char * str;
    str = itoa(rax);    
    print(str); 

    while(1){};
    return 1;

}
my readRax function :

Code: Select all

long readRax(){

    long rax;
    asm("mov %%rax, %0"
    :"=r"(rax)
    );
    return rax;
}
The problem is that on my qemu screen "0" is still displayed and not "1".
Last edited by remy on Wed Oct 21, 2015 10:50 pm, edited 1 time in total.
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: Inline assembly : reading a register

Post by Roman »

You can't rely on that code, the compiler can insert any assembly code anywhere, you can't determine the state of RAX.
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
remy
Posts: 23
Joined: Thu Nov 20, 2014 4:06 pm

Re: Inline assembly : reading a register

Post by remy »

Do you have a dummy example of how to insert the code setting RAX to 1 in my readRax() asm bloc ?
Thanks,
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: Inline assembly : reading a register

Post by BASICFreak »

Though you cannot rely on inline asm (especially for *ax, *cx, and *dx ["caller save" registers]), the only possible issue I see with the actual code is:

Code: Select all

asm(".intel_syntax noprefix");  //Use of NASM
...
asm("mov rax, 0x1");    //I try to change the default value of Rax
...
asm("mov %%rax, %0"
    :"=r"(rax)
    );
...
Why are you mixing Intel and AT&T syntax? Does the asm routine in readRax know it is AT&T syntax?

Also use volatile prefix on inline asm to keep compiler from optimizing out the ASM. (it may think rax should be 0, so the second asm instruction may be changed to "rax = 0;" by the compiler)
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: Inline assembly : reading a register

Post by Kevin »

You probably do read the value of rax. It's jus that the question doesn't make any sense because you can't know what the value in rax means at that point. The compiler is using the register to run your C code, so it has long been changed since you originally set it. You can only assume that the register stays the same within the same asm() block. You also need to specify each register that you change either in the output list or in the clobber list so that the compiler knows that you're going to overwrite its data.
Developer of tyndur - community OS of Lowlevel (German)
User avatar
Nutterts
Member
Member
Posts: 159
Joined: Wed Aug 05, 2015 5:33 pm
Libera.chat IRC: Nutterts
Location: Drenthe, Netherlands

Re: Inline assembly : reading a register

Post by Nutterts »

My best bet would be that it's somewhere on the stack. The calling convention afaik is that ax is saved and restored by whatever code that is calling your function.

Edit: Oh I overlooked that your changing the value in the function itself with inline assembly. It seems C has it's own plans with that register. You might want to disassemble that code to see whats really happening. 'objdump -d file.o > file.list'
"Always code as if the guy who ends up maintaining it will be a violent psychopath who knows where you live." - John F. Woods

Failed project: GoOS - https://github.com/nutterts/GoOS
remy
Posts: 23
Joined: Thu Nov 20, 2014 4:06 pm

Re: Inline assembly : reading a register

Post by remy »

The problem is that I was compiling with gcc's -masm=intel option.
Furthermore it is effectively not a good idea to use a system register, except if you change it in the same asm block.
Here is a solution :


Code: Select all

long readRax(){
	
	long rax;
	
	asm( "mov $1, %%rax\n" \    //Set Rax to 1
	     "mov %%rax, %0\n"  \
              :"=r"(rax)
              );
}

int main(void)
{
	
	clear();
	
	long rax;
	rax = readRax();

	while(1){};
	return 1;
}

Post Reply