Page 1 of 1
Inline assembly : reading a register [SOLVED]
Posted: Wed Oct 21, 2015 10:01 am
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".
Re: Inline assembly : reading a register
Posted: Wed Oct 21, 2015 10:33 am
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.
Re: Inline assembly : reading a register
Posted: Wed Oct 21, 2015 10:49 am
by remy
Do you have a dummy example of how to insert the code setting RAX to 1 in my readRax() asm bloc ?
Thanks,
Re: Inline assembly : reading a register
Posted: Wed Oct 21, 2015 12:31 pm
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)
Re: Inline assembly : reading a register
Posted: Wed Oct 21, 2015 12:46 pm
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.
Re: Inline assembly : reading a register
Posted: Wed Oct 21, 2015 2:43 pm
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'
Re: Inline assembly : reading a register
Posted: Wed Oct 21, 2015 10:47 pm
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;
}