2

I would like to move a variable that is pointed by a pointer to another pointer using inline assembly. And as we all know that in X86 there is no memory-memory instruction. Therefore moving from one memory location to another will always go through a x86 register. As I would like to track this mov instructions in a simulator, I extend the instruction by adding a prefix to the mov instruction.

Coming to my problem, when I add a prefix to the mov instruction and view the assembly file via -S flag, only one of the mov instruction has a prefix, whereas I would like all the instructions involved in moving the variable via the pointer to have the prefix, How can I achieve this.

My simple workload is as follows:

#include <stdio.h>
#include <stdlib.h>

template<typename T>
void spmmov(T &dst, T &src) {
  
  asm("repne;nop");
  asm("repne;movl  %1, %0"

       : "=r"(dst)
       : "m" (src)
       : // no clobbers
    );

 
}

void movetospm(int *dst, int *src) 
{
    spmmov(*dst, *src);
}

int main()
{
  
    int x = 700;

    int y = 50;


    int *Pointer2 = &y;

    int *Pointer = &x;
    movetospm(Pointer2,Pointer);
    printf("%d\n",*Pointer2);
    printf("%d\n",x);



}
 

compiled with the -S flag i get the following output for my spmmov function:

  _Z6spmmovIiEvRT_S1_:
.LFB17:
    .cfi_startproc
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
#APP
# 7 "newspm.cpp" 1
    repne;nop
# 0 "" 2
#NO_APP
    movq    -16(%rbp), %rax    #would like this one to have the repne prefix 
#APP
# 14 "newspm.cpp" 1
    repne;movl  (%rax), %edx
# 0 "" 2
#NO_APP
    movq    -8(%rbp), %rax    #would like this one to have the repne prefix 
    movl    %edx, (%rax)    #would like this one to have the repne prefix 
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc 

As stated in the comments of the assembly code, is it possible to have all the mov instructions to have the repne prefix?

any help would be appreciated.

newww
  • 65
  • 4
  • That's a bit weird; you're using an `m` constraint but the compiler is assigning a register. – Nate Eldredge Jul 08 '20 at 13:49
  • I am willing to say this is a codegen failure, and as far as I can see it is something all online compilers do. Having said that, I am not sure if there are any stated expectations for the quality of inline ASM. – SergeyA Jul 08 '20 at 13:50
  • 1
    What compiler are you using, version, options? I can't reproduce the code you're getting. gcc and clang both seem to leave the source operand in memory as they should. Of course, if you want the moves from and to memory to both have prefixes, you'll have to write both instructions in your inline asm. As it stands, you are telling the compiler that `dst` should go to a register, and so then it's up to the compiler to move it back into memory, and of course the compiler has no reason to use the prefix. – Nate Eldredge Jul 08 '20 at 13:58
  • 1
    For instance, `asm("repne; movl %1, %%eax; repne; movl %%eax, %0" : "=m" (dst) : "m" (src) : "ax");`. – Nate Eldredge Jul 08 '20 at 13:59
  • @NateEldredge am using the gcc version 7.5 running on Ubuntu, – newww Jul 08 '20 at 14:01
  • I'm not seeing such code with gcc 7.5 on [godbolt](https://godbolt.org/z/8wfD8S). Are you quite certain the output is coming from the same source file you showed (e.g. you saved all your source files and recompiled)? – Nate Eldredge Jul 08 '20 at 14:04
  • 1
    @NateEldredge I think I might have messed up with my file names, the output is of a previous file, let me change that, and am really sorry for that. – newww Jul 08 '20 at 14:08
  • 2
    Instead of using a prefix, consider adding a `nop` instruction before that. If you want a marker that stands out, use an `lnop` with a distinct memory operand. Prefixes can actually change the behaviour of instructions so they should be avoided when not necessary. For example, `rep nop` is `pause` and `rep` on `mov` is used with some new Intel extensions for transactional memory. – fuz Jul 08 '20 at 14:10
  • 1
    Note also that only the code between `#APP` and `#NO_APP` is from your inline assembly. Everything else is code the compiler has generated which you cannot directly influence. – fuz Jul 08 '20 at 14:12
  • *And as we all know that in X86 there is no memory-memory instruction* - Not quite true, and compilers will sometimes sometimes `push mem` to pass stack args (unlikely in 64-bit calling conventions). It's also rare for them to inline `rep movs` for memcpy, but it does exist. [What x86 instructions take two (or more) memory operands?](https://stackoverflow.com/q/52573554) - only ones that have at least one *implicit* memory operand. – Peter Cordes Jul 09 '20 at 18:13

0 Answers0