public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Struggling with conversion to AMD64/Linux syscalls in  inline   asm
@ 2010-01-25 14:49 me
  2010-01-25 15:08 ` Cedric Roux
  0 siblings, 1 reply; 8+ messages in thread
From: me @ 2010-01-25 14:49 UTC (permalink / raw)
  To: gcc-help

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.

BTW what a great mailing list. Thx for your responsiveness.




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Struggling with conversion to AMD64/Linux syscalls in  inline    asm
  2010-01-25 14:49 Struggling with conversion to AMD64/Linux syscalls in inline asm me
@ 2010-01-25 15:08 ` Cedric Roux
  0 siblings, 0 replies; 8+ messages in thread
From: Cedric Roux @ 2010-01-25 15:08 UTC (permalink / raw)
  To: me; +Cc: gcc-help

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.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Struggling with conversion to AMD64/Linux syscalls in  inline  asm
  2010-01-24 14:51 me
  2010-01-25  4:19 ` Jie Zhang
  2010-01-25  9:35 ` Thomas Martitz
@ 2010-01-25 10:35 ` Cedric Roux
  2 siblings, 0 replies; 8+ messages in thread
From: Cedric Roux @ 2010-01-25 10:35 UTC (permalink / raw)
  To: me; +Cc: gcc-help

Hi me,

me wrote:
> I'm trying to convert some 32 bit linked asm (which runs fine) 
> into 64 bit inline asm (g++) but am stumbling at the first hurdle
> ie I'm getting -14 returned as the file descriptor for /dev/vcsa1.

Do you have the rights to access this file?
On the host here, it's not available to ordinary users.
(but see below, there is another problem)
(try a normal C++ program and check if the access is allowed)

> Here's my attempt.
> 
> [code]
> //My amd64 inline asm version 
> #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; //ie initialised to fail unless replaced by value 
> 
>    //1 open /dev/vcsa1 & return file descriptor in rax  
>    __asm__ __volatile__(
>    ".equ sys_open, 2\n"
>    ".equ O_RDWR, 02\n" 
>    "mov $sys_open, %%rax\n" 
>    "mov $O_RDWR, %%rcx\n" 
>    "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for AMD64?
>    "syscall\n" 
>    :"=b"(test_str), "=a"(test_int)
>    :"b"(fl)

wrong registers.
Try that instead:
    __asm__ __volatile__(
    ".equ sys_open, 2\n"
    ".equ O_RDWR, 02\n"
    "mov $sys_open, %%rax\n"
    "mov $O_RDWR, %%rsi\n"
    "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for AMD64?
    "syscall\n"
    :"=a"(test_int)
    :"D"(fl)
    );

Check the documentation of linux syscall on AMD64
(sorry, no links, must not be too hard to get though...).
I just compiled a normal open to see what was
done by libc, leading to the change.
I'm not very familiar with amd64 and linux syscalls.

Note that your test_str does not make much sense.
What your asm statement does is replace the address
it points to to fl. And by the way you are double lucky
it works since the string  full of ' ' you allocate would
exist in read-only memory and normally you should
have a crash, but since you don't touch it at all,
you are well, triply lucky. (If I understand what
you /expected/, not what you actually /wrote/.)

>    ); 
>   
>    //test file name in rbx and returned file descriptor
>    cout << test_str << endl; // /dev/vcsa1                     pass
>    cout << test_int << endl; // 2 before syscall -14 after ie  fail  
> }
> 
> int main(){
>    my_fn();
>    return 0;
> }
> [/code]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Struggling with conversion to AMD64/Linux syscalls in  inline   asm
  2010-01-25  8:47     ` Jie Zhang
@ 2010-01-25 10:07       ` Jie Zhang
  0 siblings, 0 replies; 8+ messages in thread
From: Jie Zhang @ 2010-01-25 10:07 UTC (permalink / raw)
  To: me; +Cc: Jie Zhang, gcc-help

On 01/25/2010 04:47 PM, Jie Zhang wrote:
> On 01/25/2010 04:39 PM, me wrote:
>> On Mon, 25 Jan 2010 12:18:51 +0800
>> Jie Zhang<jie.zhang@analog.com> wrote:
>>
>>> On 01/24/2010 10:51 PM, me wrote:
>>>> I'm trying to convert some 32 bit linked asm (which runs fine)
>>>> into 64 bit inline asm (g++) but am stumbling at the first hurdle
>>>> ie I'm getting -14 returned as the file descriptor for /dev/vcsa1.
>>>>
>>>> Here's my attempt.
>>>>
>>>> [code]
>>>> //My amd64 inline asm version
>>>> #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; //ie initialised to fail unless replaced by
>>>> value
>>>>
>>>> //1 open /dev/vcsa1& return file descriptor in rax
>>>> __asm__ __volatile__(
>>>> ".equ sys_open, 2\n"
>>>> ".equ O_RDWR, 02\n"
>>>> "mov $sys_open, %%rax\n"
>>>> "mov $O_RDWR, %%rcx\n"
>>>> "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for
>>>> AMD64? "syscall\n"
>>>> :"=b"(test_str), "=a"(test_int)
>>>> :"b"(fl)
>>>
>>> This statement does not tell gcc the connections between registers
>>> and C variables. So there is no guarantee that those variables will
>>> be put into the registers you expect by the above statement.
>>>
>> I'm grateful for your comment but don't really understand it.
>> i.e. If...
>>> :"=b"(test_str), "=a"(test_int)
>>> :"b"(fl)
>> didn't connect the c variable "fl" to the register "rbx" then I'm not
>> sure how
>
Oops. I overlooked there is only on register in class 'a' for AMD64. So 
it definitely connects the register with the variable. Sorry!


Jie

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Struggling with conversion to AMD64/Linux syscalls in  inline  asm
  2010-01-24 14:51 me
  2010-01-25  4:19 ` Jie Zhang
@ 2010-01-25  9:35 ` Thomas Martitz
  2010-01-25 10:35 ` Cedric Roux
  2 siblings, 0 replies; 8+ messages in thread
From: Thomas Martitz @ 2010-01-25  9:35 UTC (permalink / raw)
  To: gcc-help

Am 24.01.2010 15:51, schrieb me:
> I'm trying to convert some 32 bit linked asm (which runs fine)
> into 64 bit inline asm (g++) but am stumbling at the first hurdle
> ie I'm getting -14 returned as the file descriptor for /dev/vcsa1.
>
> Here's my attempt.
>
> [code]
> //My amd64 inline asm version
> #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; //ie initialised to fail unless replaced by value
>
>     //1 open /dev/vcsa1&  return file descriptor in rax
>     __asm__ __volatile__(
>     ".equ sys_open, 2\n"
>     ".equ O_RDWR, 02\n"
>     "mov $sys_open, %%rax\n"
>     "mov $O_RDWR, %%rcx\n"
>     "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for AMD64?
>     "syscall\n"
>     :"=b"(test_str), "=a"(test_int)
>     :"b"(fl)
>     );
>
>     //test file name in rbx and returned file descriptor
>     cout<<  test_str<<  endl; // /dev/vcsa1                     pass
>     cout<<  test_int<<  endl; // 2 before syscall -14 after ie  fail
> }
>
> int main(){
>     my_fn();
>     return 0;
> }
> [/code]
>
> I'd be grateful if someone could tell me where I'm going wrong.
>
>    

Didn't the syscall numbers change in 64bit? I'm not sure.

Best regards.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Struggling with conversion to AMD64/Linux syscalls in  inline  asm
       [not found]   ` <20100125083945.45d501bd@me-desktop>
@ 2010-01-25  8:47     ` Jie Zhang
  2010-01-25 10:07       ` Jie Zhang
  0 siblings, 1 reply; 8+ messages in thread
From: Jie Zhang @ 2010-01-25  8:47 UTC (permalink / raw)
  To: me; +Cc: gcc-help

On 01/25/2010 04:39 PM, me wrote:
> On Mon, 25 Jan 2010 12:18:51 +0800
> Jie Zhang<jie.zhang@analog.com>  wrote:
>
>> On 01/24/2010 10:51 PM, me wrote:
>>> I'm trying to convert some 32 bit linked asm (which runs fine)
>>> into 64 bit inline asm (g++) but am stumbling at the first hurdle
>>> ie I'm getting -14 returned as the file descriptor for /dev/vcsa1.
>>>
>>> Here's my attempt.
>>>
>>> [code]
>>> //My amd64 inline asm version
>>> #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; //ie initialised to fail unless replaced by
>>> value
>>>
>>>      //1 open /dev/vcsa1&   return file descriptor in rax
>>>      __asm__ __volatile__(
>>>      ".equ sys_open, 2\n"
>>>      ".equ O_RDWR, 02\n"
>>>      "mov $sys_open, %%rax\n"
>>>      "mov $O_RDWR, %%rcx\n"
>>>      "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for
>>> AMD64? "syscall\n"
>>>      :"=b"(test_str), "=a"(test_int)
>>>      :"b"(fl)
>>
>> This statement does not tell gcc the connections between registers
>> and C variables. So there is no guarantee that those variables will
>> be put into the registers you expect by the above statement.
>>
>>
>> Jie
>
> I'm grateful for your comment but don't really understand it.
> i.e. If...
>>      :"=b"(test_str), "=a"(test_int)
>>      :"b"(fl)
> didn't connect the c variable "fl" to the register "rbx" then I'm not sure how

You need to take a look at this:

http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Extended-Asm.html#Extended-Asm

>>      cout<<  test_str
> would be able to print "/dev/vcsa1" because the way the program works
> it can only get this value from "rbx" suggesting that the two are connected.
>
I think it just happened by lucky.


Jie

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Struggling with conversion to AMD64/Linux syscalls in  inline  asm
  2010-01-24 14:51 me
@ 2010-01-25  4:19 ` Jie Zhang
       [not found]   ` <20100125083945.45d501bd@me-desktop>
  2010-01-25  9:35 ` Thomas Martitz
  2010-01-25 10:35 ` Cedric Roux
  2 siblings, 1 reply; 8+ messages in thread
From: Jie Zhang @ 2010-01-25  4:19 UTC (permalink / raw)
  To: me; +Cc: gcc-help

On 01/24/2010 10:51 PM, me wrote:
> I'm trying to convert some 32 bit linked asm (which runs fine)
> into 64 bit inline asm (g++) but am stumbling at the first hurdle
> ie I'm getting -14 returned as the file descriptor for /dev/vcsa1.
>
> Here's my attempt.
>
> [code]
> //My amd64 inline asm version
> #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; //ie initialised to fail unless replaced by value
>
>     //1 open /dev/vcsa1&  return file descriptor in rax
>     __asm__ __volatile__(
>     ".equ sys_open, 2\n"
>     ".equ O_RDWR, 02\n"
>     "mov $sys_open, %%rax\n"
>     "mov $O_RDWR, %%rcx\n"
>     "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for AMD64?
>     "syscall\n"
>     :"=b"(test_str), "=a"(test_int)
>     :"b"(fl)

This statement does not tell gcc the connections between registers and C 
variables. So there is no guarantee that those variables will be put 
into the registers you expect by the above statement.


Jie

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Struggling with conversion to AMD64/Linux syscalls in  inline asm
@ 2010-01-24 14:51 me
  2010-01-25  4:19 ` Jie Zhang
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: me @ 2010-01-24 14:51 UTC (permalink / raw)
  To: gcc-help

I'm trying to convert some 32 bit linked asm (which runs fine) 
into 64 bit inline asm (g++) but am stumbling at the first hurdle
ie I'm getting -14 returned as the file descriptor for /dev/vcsa1.

Here's my attempt.

[code]
//My amd64 inline asm version 
#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; //ie initialised to fail unless replaced by value 

   //1 open /dev/vcsa1 & return file descriptor in rax  
   __asm__ __volatile__(
   ".equ sys_open, 2\n"
   ".equ O_RDWR, 02\n" 
   "mov $sys_open, %%rax\n" 
   "mov $O_RDWR, %%rcx\n" 
   "mov $0600, %%rdx\n" //read/write for user in x86. Not sure for AMD64?
   "syscall\n" 
   :"=b"(test_str), "=a"(test_int)
   :"b"(fl)
   ); 
  
   //test file name in rbx and returned file descriptor
   cout << test_str << endl; // /dev/vcsa1                     pass
   cout << test_int << endl; // 2 before syscall -14 after ie  fail  
}

int main(){
   my_fn();
   return 0;
}
[/code]

I'd be grateful if someone could tell me where I'm going wrong.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-01-25 15:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-25 14:49 Struggling with conversion to AMD64/Linux syscalls in inline asm me
2010-01-25 15:08 ` Cedric Roux
  -- strict thread matches above, loose matches on Subject: below --
2010-01-24 14:51 me
2010-01-25  4:19 ` Jie Zhang
     [not found]   ` <20100125083945.45d501bd@me-desktop>
2010-01-25  8:47     ` Jie Zhang
2010-01-25 10:07       ` Jie Zhang
2010-01-25  9:35 ` Thomas Martitz
2010-01-25 10:35 ` Cedric Roux

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).