c++assemblyvisual-c++x86disassembly

_asm swap and compiler additions


I've just written a bubble_sort of an integer array (see previous question) and decided to ignore the standard swap and implement an assembly swap, which looks like this:

int swap(int* x, int* y)
{
if(x != y)
  {
       _asm
      {
        mov eax,[x];
        mov ebx, [y];
        mov [y],eax;
        mov [x], ebx;
      }
    }
return 0;
}

I was actually sure that it will be inserted into the resulting code as is and will work. Well, my code which uses this swap does work, but I've looked into what the complier turned it into, and my swap was changed into this:

if(x != y)
00E01A6F  inc         ebp  
00E01A70  or          byte ptr [ebx],bh  
00E01A72  inc         ebp  
00E01A73  or          al,74h  
if(x != y)
00E01A75  or          al,8Bh  
  {
       _asm
      {
        mov eax,[x];
00E01A77  inc         ebp  
00E01A78  or          byte ptr [ebx+45890C5Dh],cl  
        mov [y],eax;
00E01A7E  or          al,89h  
        mov [x], ebx;
00E01A80  pop         ebp  
00E01A81  or          byte ptr [ebx],dh  
      }
   }
return 0;
00E01A83  rcr         byte ptr [edi+5Eh],5Bh  
}

I've compiled it in MS VS 2012. What do all those extra lines mean, and why are they there? Why can't my _asm fragment just be used?


Solution

  • It's missing the first and last bytes. If you look at what the code is now:

    inc ebp                    ; 45
    or byte ptr [ebx],bh       ; 08 3B
    inc ebp                    ; 45
    or al,74h                  ; 0C 74
    or al,8Bh                  ; 0C 8B
    inc ebp                    ; 45
    or byte ptr [ebx+45890C5Dh],cl ; 08 8B 5D 0C 89 45
    or al,89h                  ; 0C 89
    pop ebp                    ; 5B
    or byte ptr [ebx],dh       ; 08 33
    rcr byte ptr [edi+5Eh],5Bh ; C0 5F 5E 5B
    

    If you ignore the first two bytes, you get this:

      cmp eax, [ebp + 12] ; 3B 45 0C
      jz skip             ; 74 0C
      mov eax, [ebx + 8]  ; 8B 45 08
      mov ebx, [ebp + 12] ; 8B 5D 0C 
      mov [ebp + 12], eax ; 89 45 0C 
      mov [ebx + 8], ebx  ; 89 5B 08 
    skip:
      xor eax, eax        ; 33 C0
      pop edi             ; 5F
      pop esi             ; 5E
      pop ebp             ; 5B
    

    It's missing the ret at the end, and, crucially, some instruction that has eax and [ebp + 8] as arguments (a mov would make sense there). The missing first byte desynchronized the disassembly with the instruction stream.

    It's also missing the prologue, of course.