At & t asm inline C ++ problem

My code

const int howmany = 5046;
char buffer[howmany];
    asm("lea     buffer,%esi"); //Get the address of buffer
    asm("mov     howmany,%ebx");         //Set the loop number
    asm("buf_loop:");                      //Lable for beginning of loop
    asm("movb     (%esi),%al");             //Copy buffer[x] to al
    asm("inc     %esi");                   //Increment buffer address
    asm("dec     %ebx");                   //Decrement loop count
    asm("jnz     buf_loop");              //jump to buf_loop if(ebx>0)

My problem

I am using the gcc compiler. For some reason, my buffer / howmany variables are undefined in the eyes of my asm. I do not know why. I just want to move the starting address of my buffer array into the esi register, loop it "howmany" times, copying each element to al-register.

+1
source share
3 answers

Do you use inline assembler in gcc? (If not, then in which other C ++ compiler exactly?)

If gcc, see details here , and in particular this example:

    asm ("leal (%1,%1,4), %0"
         : "=r" (five_times_x)
         : "r" (x) 
         );

%0 %1 C, ( ) ( ) asm. "", ( , /* no output registers */, ).

+7

,

int howmany = 5046;
char buffer[howmany];

++. ++ . ++ .

, , . , , . , buffer , . , esi

mov buffer,%esi

lea, . lea "" , .

: . , ? howmany

const int howmany = 5046;

"" ++-, (.. lea).

+1

asm asm, , ( , ), //clobber .

lea mov / C ( / , asm- , ).

, mov , , . GNU C inline asm , .

BTW, GNU ++ C99, howmany const , . , asm GNU, .


, https://gcc.gnu.org/wiki/DontUseInlineAsm. asm, asm , gcc , inline-asm. asm , ( , ).

%[ptr] %2 %%ebx. , , , , x86 , "r", , "=a" rax/eax/ax/al. . https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html, inline-assembly wiki..

buf_loop%=: , , , .

+ asm output Godbolt

void ext(char *);

int foo(void) 
{
    int howmany = 5046;   // could be a function arg
    char buffer[howmany];
    //ext(buffer);

    const char *bufptr = buffer;  // copy the pointer to a C var we can use as a read-write operand
    unsigned char result;
    asm("buf_loop%=:  \n\t"                 // do {
        "   movb     (%[ptr]), %%al \n\t"   // Copy buffer[x] to al
        "   inc     %[ptr]        \n\t"
        "   dec     %[count]      \n\t"
        "   jnz     buf_loop      \n\t"      // } while(ebx>0)
       :   [res]"=a"(result)      // al = write-only output
         , [count] "+r" (howmany) // input/output operand, any register
         , [ptr] "+r" (bufptr)
       : // no input-only operands
       : "memory"   // we read memory that isn't an input operand, only pointed to by inputs
    );
    return result;
}

%%al , : Extended Asm ( ) %, % asm-. %[res] %0 %al asm-. ( , cbw lodsb - .) result is unsigned char, . , %b[count], .

"memory" clobber, . , , , buffer[] C. ( ).

gcc7.2 -O3 :

    pushq   %rbp
    movl    $5046, %edx
    movq    %rsp, %rbp
    subq    $5056, %rsp
    movq    %rsp, %rcx         # compiler-emitted to satisfy our "+r" constraint for bufptr
    # start of the inline-asm block
    buf_loop18:  
       movb     (%rcx), %al 
       inc     %rcx        
       dec     %edx      
       jnz     buf_loop      
    # end of the inline-asm block

    movzbl  %al, %eax
    leave
    ret

, leave asm, , inline asm . , , .


, , asm. . inline GNU Assembler , , , .

C , ++, using .

int bar(unsigned howmany)
{
    //int howmany = 5046;
    char buffer[howmany];
    //ext(buffer);
    buffer[0] = 1;
    buffer[100] = 100;   // test whether we got the input constraints right

    //using input_t = const struct {char a[howmany];};  // requires a constant size
    using flexarray_t = const struct {char a; char x[];};
    const char *dummy;
    unsigned char result;
    asm("buf_loop%=:  \n\t"                 // do {
        "   movb     (%[ptr]), %%al \n\t"   // Copy buffer[x] to al
        "   inc     %[ptr]        \n\t"
        "   dec     %[count]      \n\t"
        "   jnz     buf_loop      \n\t"      // } while(ebx>0)
       : [res]"=a"(result)        // al = write-only output
         , [count] "+r" (howmany) // input/output operand, any register
         , "=r" (dummy)           // output operand in the same register as buffer input, so we can modify the register
       : [ptr] "2" (buffer)     // matching constraint for the dummy output
         , "m" (*(flexarray_t *) buffer)  // whole buffer as an input operand

           //, "m" (*buffer)        // just the first element: doesn't stop the buffer[100]=100 store from sinking past the inline asm, even if you used asm volatile
       : // no clobbers
    );
    buffer[100] = 101;
    return result;
}

, buffer , , . foo(), const char *bufptr = buffer;, , , C - , . C, , , ( : int dummy .)

Assignments buffer[100] = 100;and buffer[100] = 101;lie in the fact that they both appear in the asm instead be combined into inline-asm (what happens if you do not consider the input operand "m"). IDK, why buffer[100] = 101;not optimized; he is dead, it should be so. Also note that asm volatilethis reordering does not block, so it is not an alternative to clobber "memory"or uses the correct restrictions.

+1
source

Source: https://habr.com/ru/post/1694352/


All Articles