Re: Struggling with conversion to AMD64/Linux syscalls in inline asm

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



me wrote:
I now get a file descriptor of 3 when opening /dev/vcsa1 thanks to Bob
Platz, Jie Zhang, Thomas Martiz & Cedrix Roux. Bob and Cedric showed me
that the registers used in 64bit linux are different. Both codes now
give 3 which seems reasonable.

Unfortunately I'm now stuck on the read bit. Here's where I've got to
so far...

//My amd64 inline asm version
//this now returns a file descriptor of 3
#include <iostream>
using namespace std;

void my_fn(){
   const char * fl =       "/dev/vcsa1";
   const char * test_str = "          "; //make same size as fl
int test_int = -1; //fails unless replaced by value unsigned char buf[] = {0,0,0,0};

//1 open /dev/vcsa1 & return file descriptor in rax __asm__ __volatile__(
   ".equ sys_open,2\n"
   ".equ O_RDWR,02\n"
"movq $sys_open,%%rax\n" "movq $O_RDWR,%%rsi\n" "movq $0600,%%rdx\n" //read/write for user in x86. Not sure for AMD64? "syscall\n" :"=D"(test_str),"=a"(test_int)
   :"D"(fl)              //rdi
   :"rsi","rdx","rcx","r10","r11","cc" //Is this enough
);
   //cout << test_str << endl; // /dev/vcsa1    ie pass
   //cout << test_int << endl; // 3             ie pass

   //read 1st 4 bytes of file into buf[]
   __asm__ __volatile__(
   "movq %%rax, %%rsi\n"   //returned file descriptor into rsi
   "movq $0,%%rax\n"      //syscall read into rax
   "movq $4,%%rdx\n"      //qty of bytes to read into rdx
"syscall\n" :"=a"(test_int)
   :"D"(&buf[0])          //ptr of where to place 1st byte into rdi
   :"rsi","rdx","rcx","r10","r11","cc"
   );
cout << test_int << endl; //returning -9 expected 4 ie fail }

int main(){
   my_fn();
   return 0;
}

Yes the syscall numbers in 64 bit linux is different to x86 and I do
take the point that I'm lucky with my output variables.

I expect read to return 4 instead of -9.

Read that:
http://www.x86-64.org/documentation/abi.pdf
especially appendix A.

You see that order of registers is %rdi, %rsi, %rdx, %rcx, ...
read is  ssize_t read(int fd, void *buf, size_t count);

so put fd in %rdi, buf in %rsi, and count in %rdx

So in your code replace "rsi" by "rdi" and 'D' by 'S'
(and don't forget to change rsi in the clobber list too,
but is it necessary to put all what you put in there?
I don't know; this list is to tell gcc what registers
the asm statement changes, I doubt syscall changes
anything; anyway, some more experienced people may
give you nice pointers with good explanations).

Regards,
Cédric.

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux