LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How to use constraints "m" in gcc inline assembly when I pass a string ? (https://www.linuxquestions.org/questions/programming-9/how-to-use-constraints-m-in-gcc-inline-assembly-when-i-pass-a-string-4175521089/)

mirage1993 10-05-2014 06:41 AM

How to use constraints "m" in gcc inline assembly when I pass a string ?
 
In this program
Code:

char get_fs_byte(char * s)
{
        char c;

        __asm__("movb %%fs:%1, %0":"=r"(c):"m"(*s));

        return c;
}

and
this
Code:

char get_fs_byte(char * s)
{
        char c;

        __asm__("movb %%fs:%1, %0":"=r"(c):"m"(s));

        return c;
}

what is the difference between
Code:

"m"(*s)
and
Code:

"m"(s)
.

NevemTeve 10-06-2014 03:15 AM

Are you absolutely sure you want to do this? Your program will be dependent on one single platform and one single compiler.

mirage1993 10-06-2014 03:17 AM

Quote:

Originally Posted by NevemTeve (Post 5249545)
Are you absolutely sure you want to do this? Your program will be dependent on one single platform and one single compiler.

In fact,I just want to know their difference .:)

NevemTeve 10-06-2014 03:22 AM

Then, I suppose, you have learned these by heart:
http://www.ibiblio.org/gferg/ldp/GCC...bly-HOWTO.html
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

mirage1993 10-06-2014 03:44 AM

Quote:

Originally Posted by NevemTeve (Post 5249548)

I had read these before I posted this post.
when I use "m"(*s). I am confused . Is "%1" a pointer to a string or the first characters of a string ?

NevemTeve 10-06-2014 04:00 AM

And how did you try to debug it?

ntubski 10-06-2014 01:51 PM

Quote:

Originally Posted by mirage1993 (Post 5249222)
what is the difference between
Code:

"m"(*s)
and
Code:

"m"(s)
.

Try disassembling the result and see.

johnsfine 10-07-2014 07:58 AM

Quote:

Originally Posted by ntubski (Post 5249811)
Try disassembling the result and see.

The point of such a constraint is that usually it makes no difference in the generated code, but in some complicated situations (typically when the function containing it is inlined into a caller) it affects some transformation that the optimizer makes to a related piece of code.

I don't know those syntax details myself. I rarely use asm, and only for large enough chunks that grossly suppressing optimization of the bordering C++ code is easier and makes sense (compared to fine tuning the constraints).

For your suggestion to make sense, one would need to first have a very good understanding of the optimizer and then construct a much more complicated example in which the correct vs. incorrect syntax for the constraint makes a difference in the optimization of surrounding code (with the incorrect syntax either allowing an incorrect optimization or preventing a correct optimization).

Understanding the syntax specification would be better than such experimentation. I expect someone in this forum does understand those syntax details. I don't.

ntubski 10-07-2014 08:50 AM

Quote:

Originally Posted by johnsfine (Post 5250167)
The point of such a constraint...

If you look closely at the question, the difference between the 2 cases is not the constraint, but the input:

Code:

"m"(*s)                              "m"(s)
push  %rbp                          push  %rbp
mov    %rsp,%rbp                      mov    %rsp,%rbp
mov    %rdi,-0x18(%rbp)              mov    %rdi,-0x18(%rbp)
mov    -0x18(%rbp),%rax           
mov    %fs:(%rax),%al                mov    %fs:-0x18(%rbp),%al
mov    %al,-0x1(%rbp)                mov    %al,-0x1(%rbp)
movzbl -0x1(%rbp),%eax                movzbl -0x1(%rbp),%eax
pop    %rbp                          pop    %rbp
retq                                  retq


mirage1993 10-07-2014 10:08 AM

Quote:

Originally Posted by ntubski (Post 5250182)
If you look closely at the question, the difference between the 2 cases is not the constraint, but the input:

Code:

"m"(*s)                              "m"(s)

OK,OK.I have understand a little.
I write another program.
Code:

#include<stdio.h>
void main()
{
    char c;
    //int tmp;
    char *s="abcdefg";
    asm("movb %1,%0\n\t"
    :"=d"(c)
    :"m"(*s));
    printf("out:%c\n",c);
}

In this code , "%1" represent a character "a"
and in the next code
Code:

#include<stdio.h>
void main()
{
    //char c;
    int tmp;
    char *s="abcdefg";
    printf("%d\n",s);
    asm("movl %1,%0\n\t"
    :"=d"(tmp)
    :"m"(s));
    printf("out:%d\n",tmp);
}

"%1" represent a pointer to the string "abcdefg".In another words ,"%1" represent a pointer to 'a'.
Note:tmp==s

Besides,in the next code
Code:

#include<stdio.h>
void main()
{
    char c;
    //int tmp;
    char *s="abcdefg";
    //printf("%d\n",s);
    asm("movb %%ds:%1,%0\n\t"
    :"=d"(c)
    :"m"(*s));
    printf("out:%c\n",c);
}

"%1" represent an offset to "abcdefg".

So,in addition to passing information in registers, gcc can understand references to raw memory. This will expand to some more complex addressing mode within the asm string.See this http://locklessinc.com/articles/gcc_asm/

What the "%1" represent is not important, because it changes all the time relying on the addressing mode.

Am I right?:D

Thanks all the people!

ntubski 10-10-2014 10:27 PM

Quote:

Originally Posted by mirage1993 (Post 5250219)
Code:

    char *s="abcdefg";
    asm("movb %1,%0\n\t"
    :"=d"(c)
    :"m"(*s));

In this code , "%1" represent a character "a"

yes.

Quote:

and in the next code
Code:

    char *s="abcdefg";
    printf("%d\n",s);
    asm("movl %1,%0\n\t"
    :"=d"(tmp)
    :"m"(s));

"%1" represent a pointer to the string "abcdefg".In another words ,"%1" represent a pointer to 'a'.
yes.

Quote:

Besides,in the next code
Code:

    char *s="abcdefg";
    //printf("%d\n",s);
    asm("movb %%ds:%1,%0\n\t"
    :"=d"(c)
    :"m"(*s));

"%1" represent an offset to "abcdefg".
No, it represents 'a' again. Simply because *s == 'a'.

Quote:

This will expand to some more complex addressing mode within the asm string.See this http://locklessinc.com/articles/gcc_asm/

What the "%1" represent is not important, because it changes all the time relying on the addressing mode.
Note that by using "m" you force "%1" to be a memory reference, even when the value could go into (or is already in) a register.

mirage1993 10-10-2014 11:06 PM

Quote:

Originally Posted by ntubski (Post 5252160)
No, it represents 'a' again. Simply because *s == 'a'.

But ,when I use "gcc example.c -S" to compile

Code:

movb %%ds:%1,%0
is compiled to
Code:

movb %ds:(%eax),%edx
why..

johnsfine 10-11-2014 06:33 AM

Quote:

Originally Posted by mirage1993 (Post 5252165)
Code:

movb %%ds:%1,%0
is compiled to
Code:

movb %ds:(%eax),%edx
why..

Notice the () around %eax where you did not have () around %1

%eax is s

(%eax) is *s

%1 is the whole expression (%eax) not just the register %eax

The only difference vs. the earlier *s example that you seem to understand is the %ds: but that makes no actual difference.

mirage1993 10-11-2014 08:20 AM

Quote:

Originally Posted by johnsfine (Post 5252265)
Notice the () around %eax where you did not have () around %1

%eax is s

(%eax) is *s

%1 is the whole expression (%eax) not just the register %eax

The only difference vs. the earlier *s example that you seem to understand is the %ds: but that makes no actual difference.

if (%eax) is 'a',
Code:

movb %%ds:%1,%0
means
Code:

movb %ds:a,%0
a little strange......

ntubski 10-11-2014 01:01 PM

Quote:

Originally Posted by mirage1993 (Post 5252291)
if (%eax) is 'a',
Code:

movb %%ds:%1,%0
means
Code:

movb %ds:a,%0

No, you can't apply memory segments like that. If (%eax) is 'a' then %ds:(%eax) is also 'a' (because current OSes setup the memory segments to have no effect (except for the %fs is used for thread local variables, I think)). But regardless, the segment applies to the address not the value located at the address.


All times are GMT -5. The time now is 08:31 PM.