-1

Context Simple code to highlight basic assembly. d can be ignored, I'm just trying to figure out how assembly addition looks like for now. I'm returning c "for fun".

int main()
{
    int a = 3;
    int b = 5;
    int c = a + b;

    char d[17] = "This is a string";

    return c;
}

Result This is assembly I get from Visual Studio Disassembly.

int main()
{
    00007FF705411790  push        rbp  
    00007FF705411792  push        rsi  
    00007FF705411793  push        rdi  
    00007FF705411794  sub         rsp,170h  
    00007FF70541179B  lea         rbp,[rsp+20h]  
    00007FF7054117A0  lea         rdi,[rsp+20h]  
    00007FF7054117A5  mov         ecx,24h  
    00007FF7054117AA  mov         eax,0CCCCCCCCh  
    00007FF7054117AF  rep stos    dword ptr [rdi]  
    00007FF7054117B1  lea         rcx,[__D9670FCC_test@cpp (07FF705421000h)]  
    00007FF7054117B8  call        __CheckForDebuggerJustMyCode (07FF70541135Ch)  
        int a = 3;
    00007FF7054117BD  mov         dword ptr [a],3  

        int b = 5;
    00007FF7054117C4  mov         dword ptr [b],5  

        int c = a + b;
   *00007FF7054117CB  mov         eax,dword ptr [b]  
    00007FF7054117CE  mov         ecx,dword ptr [a]  
    00007FF7054117D1  add         ecx,eax  
    00007FF7054117D3  mov         eax,ecx  
    00007FF7054117D5  mov         dword ptr [c],eax  *

        char d[17] = "This is a string";
    00007FF7054117D8  lea         rax,[d]  
    00007FF7054117DC  lea         rcx,[string "This is a string" (07FF705419C28h)]  
    00007FF7054117E3  mov         rdi,rax  
    00007FF7054117E6  mov         rsi,rcx  
    00007FF7054117E9  mov         ecx,11h  
    00007FF7054117EE  rep movs    byte ptr [rdi],byte ptr [rsi]  

        return c;
    00007FF7054117F0  mov         eax,dword ptr [c]  
}

Question I don't understand why the code for addition and assignment to c is not just either: A)

    00007FF7054117CB  mov         eax,dword ptr [b]  
    00007FF7054117CE  mov         ecx,dword ptr [a]  
    00007FF7054117D1  add         ecx,eax  

    00007FF7054117D5  mov         dword ptr [c],*ecx* 

B)

    00007FF7054117CB  mov         eax,dword ptr [b]  
    00007FF7054117CE  mov         ecx,dword ptr [a]  
    00007FF7054117D1  add         *eax,ecx*  

    00007FF7054117D5  mov         dword ptr [c],eax 

Additional information Relevant parts and changes are marked with *. On the side note, is it possible to call add with variables a and b directly? Maybe something like this?

add a, b
mov dword ptr[c], a

I understand this would change a but I wonder if it is possible?

I'm using Visual Studio 2022, ISO C++14, AMD Ryzen x64. Not sure if this is relevant, I'm new to assembly.

My thoughts I don't understand why the complier does this. Wouldn't it be faster to say just mov dword ptr [c], ecx or add eax, ecx? Is there something special about EAX? I know it's used for return value and that's why I get mov eax, dword ptr[c] for return value, but I don't see why assignment to c would require it. Aren't all registers on 64-bit systems general purpose?

Edit 1: Debug

Isutary
  • 1
  • 2
  • is it debug or release mode? – Iłya Bursov Aug 04 '23 at 21:00
  • @IłyaBursov debug – Isutary Aug 04 '23 at 21:04
  • 1
    @IłyaBursov : This is MSVC debug mode. We can see it poisoning the stack with `0CCCCCCCCh` so uninitialized data is more easily detectable. So there's zero expectation that the compiler even tried to make efficient code. [Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?](https://stackoverflow.com/q/53366394) – Peter Cordes Aug 04 '23 at 21:04
  • It's a bit surprising that it wastes an instruction in that particular way, but other compilers like GCC have their own quirks and always waste instructions in debug builds, like always evaluating expressions into the return-value reg (RAX) and then `mov edi, eax` if it was a function arg. – Peter Cordes Aug 04 '23 at 21:07
  • @IłyaBursov so debug performs no optimization in general? If I were to change it to release mode do you expect this to change? Do you have a link to differences between debug and release mode you would recommend or will a simple google search suffice? – Isutary Aug 04 '23 at 21:07
  • Anyway no, this is not faster to execute, just your compiler not spending any extra compile time to make asm that isn't dumb. See [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) for hints about writing functions that compile to asm that *is* interesting to look at. – Peter Cordes Aug 04 '23 at 21:08
  • 1
    Yes, of course a release build would be vastly different, should be just `mov eax, 8` / `ret` (returning `8` is the only externally-visible effect since none of the locals are `volatile`.) Try it yourself, locally or on https://godbolt.org/. Yup, all 4 major x86 compilers agree: https://godbolt.org/z/3oYcjPoh4 . I also included a function that adds two `int`s from memory, with `mov` / `add eax, [mem]`. – Peter Cordes Aug 04 '23 at 21:09

0 Answers0