My Home on the Internet

Main menu

Category Archives: compilers

I came across this article on the Daily WTF and it reminded me of the many issues I have with Microsoft compilers. For example, back in the VB 6 days, I remember how variables in a structure would disappear if the field they referenced in a database was NULL. This made things oh so much fun.

I also remember how Visual C++ decided to screw with new so it wouldn’t throw std::bad_alloc on allocation failure. I had a bunch of code where I had to put in things like foo = new(nothrow) all throughout my code to help it be cross platform. Or having two separate and incompatible iostreams implementations where neither was really feature complete but I needed to find a way to use both to get things to work.

For the first post on my new blog, I thought I’d be random and show what happens when you take the same small piece of code and compile it with both gcc and g++. You might be surprised that, while identical for the most part, there are some small differences in the assembly code output when targeting for C and C++.

The test program was the same for both compilers, except I saved it as both main.c and main.cpp. Note that I could have kept the same file but I was lazy and didn’t feel like forcing the compiler to output pure C code (gcc will compile for C++ when it sees a .cpp extension).

The first part of main() from both C and C++ targeted code is the same. We’ll go through it here to discuss what is happening for those who are more familiar with higher-level languages than Intel x86 assembly. These lines are pretty much standard for any subroutine in assembly language across different compilers. They set up a the new stack frame for the subroutine and save pointers from the old routine so it can be recovered upon exiting.

push ebp Push the base pointer to the stack mov ebp,esp Base and top of stack pointer equal sub esp,0x10 Allocate space for local variables in our new stack frame.

Now we get to the meat of the program. If you’ll recall, I had two local variables in the program declared as:

int i = 0; int loop;

In the assembler output, both the variables (referenced through their aliases on the stack) are initialized to zero.

We then jump to the comparison line where we test that loop (again referenced off the stack) is compared to the value 49 (0x31 in hex). This is where we see the differences in the output from targeting pure C vs. C++. I’ll copy them below from both the C and C++ target since I’ve scrolled quite a bit from up top 😉

Now for the most part they’re identical except for how we do our test to break out of the loop. In the C version, gcc uses the jle (jump if less than or equal) instruction after the comparison (cmp) to go up and add one to i and loop. In the C++ version, we first use setle (Set if less than or equal) to set the al register to 1 if the comparison matched. We then test if al is true and then we use jne to move back up in the function to do the additions. Once loop is equal to 49, we then put 0 into the EAX register and then exit the routine.

Until I go into WHY there’s this slight difference in output, for now let’s just say that gcc and g++ use some similar and some different code paths when generating machine code. Have fun and Happy Father’s Day everyone.