1

I have created a very simple x86 console program that uses Visual Studio 2019 compiler to sum 2 numbers just to see how is the program be after disassembly but I found something unclear to me.

// C++
#include <iostream>

int sum(int n, int n2) {
    return n + n2;
}

int main() {
    int result = sum(7, 3);
    std::cout << result;
}

After disassembled

; The main function from outside
Push edi
push esi
push dword ptr ds:[eax]
call <consoleapplication._main>
add esp, C

; The main function from inside
mov ecx, dword ptr ds : [<&? cout@std@@3V ? $basic_ostream@DU ? $char_traits@D@std@@@1@A>]
push A
call dword ptr ds : [<&? ? 6 ? $basic_ostream@DU ? $char_traits@D@std@@@std@@QAEAAV01@H@Z>]
xor eax, eax
ret

As you have seen in the second code block, the second line

push A

That is the result of the "sum" function but where is its body and where is the call instruction that calls it in the main function?

3
  • 1
    first of all you have already been advised quite a few times to post code and not screen shots next for a question to have a meaningful answer you need to provide context like what architecture what compiler options , which compiler, what os , optimization etc. will you understand if i reply the body may have been inlined and optimized away
    – blabb
    Dec 30 '21 at 4:15
  • Making a function static inline in C++ has a similar effect. Usually the function body will be completely inlined. In your case, however, the compiler knew sum() was only called once. It knew it was called with known (literal) arguments and so there was no point in delegating the computation to runtime. Essentially your example is constexpr without explicitly saying it. Optimizers in compilers these days are fairly smart and will catch much more convoluted cases (but fail with some trivial ones, too). Change the code to take in argc from main() and it should look different.
    – 0xC0000022L
    Jan 4 at 8:33
  • ... but even in that case your function could still be inlined (i.e. body disappears). There are actually cases where this is desired behavior and static inline on a function is one way to nudge the compiler in the right direction without using proprietary "attributes" like __forceinline.
    – 0xC0000022L
    Jan 4 at 8:35
0
  1. always post text instead of screen shots as much as possible .

  2. always provide context .

  3. the compilers , operating systems , architectures , headers everything evolve and what might have been correct yesterday might not be correct today .

  4. code with all warnings and analysis enabled as much as possible .

  5. provide a readily compilable code for some one to spend a few minutes trying to answer if you don't include headers most wont be bothered to look for them .

6) do you know your return statement has a problem called NRVO some compilers will spit cant return n+n2 named returns are not supported ?

use scopes with {} make it a habit .

and not to nitpick but printf is not c++.

i have attached a gif below that should answer your question watch it several times test and edit your question what you do not understand in that gif and whether you were able to find the answer you were looking for by watching it

enter image description here

As Commented there are several kinds of Optimization
you can read the docs for the compiler you use
for msvc cl.exe these are the Optimizations that can be performed

C:\>cl /nologo  /? | grep /O
/O1 maximum optimizations (favor space) /O2 maximum optimizations (favor speed)
/Ob<n> inline expansion (default n=0)   /Od disable optimizations (default)
/Og enable global optimization          /Oi[-] enable intrinsic functions
/Os favor code space                    /Ot favor code speed
/Ox optimizations (favor speed)

optimized code is difficult to analyze
that is why there debug build are used when writing code
optimized builds are used when releasing the code
while releasing the symbols are also stripped away so an optimized release built binary is just bytes all over which the reverse engineer has to decipher

4
  • Thank you for your tips, I have updated my question.
    – Lion King
    Dec 30 '21 at 14:32
  • -O1 and -O2 are almost generate the same disassembly code (ambiguous code), -O0 is the only one that generates the normal code. But what if I face an application that uses -O1 or -O2 optimization option How can it be analyzed then?
    – Lion King
    Dec 30 '21 at 19:23
  • 1
    O0 is debug build O1 is optimized for speed , O2 is optimized for size there are several other O's which does some special optimizations debugging optimized code is difficult and needs experience because when they are optimized the symbols are also normally stripped out. so all you have are tons of bytes to peer and decipher (thats basically reverse engineering)
    – blabb
    Dec 30 '21 at 19:29
  • 1
    While I agree with your commentary about the question, not all parts seem to apply anymore (e.g. printf) and I think they should be left in comments, instead of going into the answer. Much in the same way you (correctly!) pointed out that code should be posted instead of screenshots, your answer would have gained a bit by linking to the Compiler Explorer example.
    – 0xC0000022L
    Jan 4 at 8:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.