{"id":21,"date":"2011-06-19T17:22:00","date_gmt":"2011-06-19T21:22:00","guid":{"rendered":"http:\/\/brian.digitalmaddox.com\/blog\/?p=21"},"modified":"2014-07-08T16:46:12","modified_gmt":"2014-07-08T20:46:12","slug":"first-post-fun-with-compilers","status":"publish","type":"post","link":"https:\/\/brian.digitalmaddox.com\/blog\/?p=21","title":{"rendered":"First Post: Fun with Compilers"},"content":{"rendered":"<p>For the first post on my new blog, I thought I&#8217;d be random and show what happens when you take the same small piece of code and compile it with both gcc and g++. \u00a0You 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++.<\/p>\n<p>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&#8217;t feel like forcing the compiler to output pure C code (gcc will compile for C++ when it sees a .cpp extension).<\/p>\n<p><span>\u00a0 \u00a0int main(int argc, char* argv[])<\/span><br \/><span>\u00a0 \u00a0{<\/span><br \/><span>\u00a0 \u00a0 \u00a0int i = 0;<\/span><br \/><span>\u00a0 \u00a0 \u00a0int loop;<\/span><br \/><span>\u00a0\u00a0<\/span><br \/><span>\u00a0 \u00a0 \u00a0for (loop = 0; loop < 50; loop++)<\/span><br \/><span>\u00a0 \u00a0 \u00a0 \u00a0++i;<\/span><br \/><span><br \/><\/span><br \/><span>\u00a0 \u00a0 \u00a0return 0;<\/span><br \/><span>\u00a0 \u00a0}<\/span><\/p>\n<div><\/div>\n<p>A quick <i>gcc main.c -o main_c<\/i> and <i>g++ main.cpp -o main_cpp<\/i> took care of the output. \u00a0After that, I used <i>objdump\u00a0-DCslx -M intel<\/i> to fully disassemble the programs.<\/p>\n<p>Ignoring the differences (for now) in the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Executable_and_Linkable_Format\">ELF<\/a> output, we examine the main functions in assembler.<\/p>\n<p>Output using gcc:<\/p>\n<p><span>8048394 <main>:<\/span><br \/><span>main():<\/span><br \/><span>\u00a08048394:<span> <\/span>55 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>push \u00a0 ebp<\/span><br \/><span>\u00a08048395:<span> <\/span>89 e5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>mov \u00a0 \u00a0ebp,esp<\/span><br \/><span>\u00a08048397:<span> <\/span>83 ec 10 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>sub \u00a0 \u00a0esp,0x10<\/span><br \/><span>\u00a0804839a:<span> <\/span>c7 45 fc 00 00 00 00 <span> <\/span>mov \u00a0 \u00a0DWORD PTR [ebp-0x4],0x0<\/span><br \/><span>\u00a080483a1:<span> <\/span>c7 45 f8 00 00 00 00 <span> <\/span>mov \u00a0 \u00a0DWORD PTR [ebp-0x8],0x0<\/span><br \/><span>\u00a080483a8:<span> <\/span>eb 08 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>jmp \u00a0 \u00a080483b2 <main+0x1e><\/span><br \/><span>\u00a080483aa:<span> <\/span>83 45 fc 01 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>add \u00a0 \u00a0DWORD PTR [ebp-0x4],0x1<\/span><br \/><span>\u00a080483ae:<span> <\/span>83 45 f8 01 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>add \u00a0 \u00a0DWORD PTR [ebp-0x8],0x1<\/span><br \/><span>\u00a080483b2:<span> <\/span>83 7d f8 31 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>cmp \u00a0 \u00a0DWORD PTR [ebp-0x8],0x31<\/span><br \/><span>\u00a080483b6:<span> <\/span>7e f2 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>jle \u00a0 \u00a080483aa <main+0x16><\/span><br \/><span>\u00a080483b8:<span> <\/span>b8 00 00 00 00 \u00a0 \u00a0 \u00a0 <span> <\/span>mov \u00a0 \u00a0eax,0x0<\/span><br \/><span>\u00a080483bd:<span> <\/span>c9 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>leave \u00a0<\/span><br \/><span>\u00a080483be:<span> <\/span>c3 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>ret \u00a0 \u00a0<\/span><br \/><span>\u00a080483bf:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><\/p>\n<p>Output using g++:<br \/><span>080483f4 <main>:<\/span><\/p>\n<p><span>main():<\/span><br \/><span>\u00a080483f4:<span> <\/span>55 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>push \u00a0 ebp<\/span><br \/><span>\u00a080483f5:<span> <\/span>89 e5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>mov \u00a0 \u00a0ebp,esp<\/span><br \/><span>\u00a080483f7:<span> <\/span>83 ec 10 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>sub \u00a0 \u00a0esp,0x10<\/span><br \/><span>\u00a080483fa:<span> <\/span>c7 45 fc 00 00 00 00 <span> <\/span>mov \u00a0 \u00a0DWORD PTR [ebp-0x4],0x0<\/span><br \/><span>\u00a08048401:<span> <\/span>c7 45 f8 00 00 00 00 <span> <\/span>mov \u00a0 \u00a0DWORD PTR [ebp-0x8],0x0<\/span><br \/><span>\u00a08048408:<span> <\/span>eb 08 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>jmp \u00a0 \u00a08048412 <main+0x1e><\/span><br \/><span>\u00a0804840a:<span> <\/span>83 45 fc 01 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>add \u00a0 \u00a0DWORD PTR [ebp-0x4],0x1<\/span><br \/><span>\u00a0804840e:<span> <\/span>83 45 f8 01 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>add \u00a0 \u00a0DWORD PTR [ebp-0x8],0x1<\/span><br \/><span>\u00a08048412:<span> <\/span>83 7d f8 31 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>cmp \u00a0 \u00a0DWORD PTR [ebp-0x8],0x31<\/span><br \/><span>\u00a08048416:<span> <\/span>0f 9e c0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>setle \u00a0al<\/span><br \/><span>\u00a08048419:<span> <\/span>84 c0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>test \u00a0 al,al<\/span><br \/><span>\u00a0804841b:<span> <\/span>75 ed \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span> <\/span>jne \u00a0 \u00a0804840a <main+0x16><\/span><br \/><span>\u00a0804841d:<span> <\/span>b8 00 00 00 00 \u00a0 \u00a0 \u00a0 <span> <\/span>mov \u00a0 \u00a0eax,0x0<\/span><br \/><span>\u00a08048422:<span> <\/span>c9 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>leave \u00a0<\/span><br \/><span>\u00a08048423:<span> <\/span>c3 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>ret \u00a0 \u00a0<\/span><br \/><span>\u00a08048424:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a08048425:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a08048426:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a08048427:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a08048428:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a08048429:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a0804842a:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a0804842b:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a0804842c:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a0804842d:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a0804842e:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><br \/><span>\u00a0804842f:<span> <\/span>90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span> <\/span>nop<\/span><\/p>\n<p>The first part of main() from both C and C++ targeted code is the same. \u00a0We&#8217;ll go through it here to discuss what is happening for those who are more familiar with higher-level languages than Intel x86 assembly. \u00a0These lines are pretty much standard for any subroutine in assembly language across different compilers. \u00a0They set up a the new stack frame for the subroutine and save pointers from the old routine so it can be recovered upon exiting.<\/p>\n<p><span>\u00a0 \u00a0push \u00a0 ebp \u00a0 \u00a0 \u00a0Push the base pointer to the stack<\/span><br \/><span>\u00a0 \u00a0mov \u00a0 \u00a0ebp,esp \u00a0Base and top of stack pointer equal<\/span><br \/><span>\u00a0 \u00a0sub \u00a0 \u00a0esp,0x10 Allocate space for local variables in our new stack frame.<\/span><\/p>\n<p>Now we get to the meat of the program. \u00a0If you&#8217;ll recall, I had two local variables in the program declared as:<\/p>\n<p><span>\u00a0 \u00a0 \u00a0int i = 0;<\/span><br \/><span>\u00a0 \u00a0 \u00a0int loop;<\/span><\/p>\n<p>In the assembler output, both the variables (referenced through their aliases on the stack) are initialized to zero.<\/p>\n<p><span>\u00a0 mov \u00a0 \u00a0DWORD PTR [ebp-0x4],0x0 &#8211; explicity set to zero<\/span><br \/><span>\u00a0 mov \u00a0 \u00a0DWORD PTR [ebp-0x8],0x0 &#8211; gcc sets loop to zero implicity<\/span><\/p>\n<p>We then jump to the comparison line where we test that <i>loop<\/i> (again referenced off the stack) is compared to the value 49 (0x31 in hex). \u00a0This is where we see the differences in the output from targeting pure C vs. C++. \u00a0I&#8217;ll copy them below from both the C and C++ target since I&#8217;ve scrolled quite a bit from up top \ud83d\ude09<\/p>\n<p>Loop in C target:<\/p>\n<p><span>\u00a0 jmp \u00a0 \u00a080483b2 <main+0x1e><\/span><br \/><span>\u00a0 add \u00a0 \u00a0DWORD PTR [ebp-0x4],0x1<\/span><br \/><span>\u00a0 add \u00a0 \u00a0DWORD PTR [ebp-0x8],0x1<\/span><br \/><span>\u00a0 cmp \u00a0 \u00a0DWORD PTR [ebp-0x8],0x31<\/span><br \/><span>\u00a0 jle \u00a0 \u00a080483aa <main+0x16><\/span><\/p>\n<p>Loop in C++ target:<\/p>\n<p><span>\u00a0 jmp \u00a0 \u00a08048412 <main+0x1e><\/span><br \/><span>\u00a0 add \u00a0 \u00a0DWORD PTR [ebp-0x4],0x1<\/span><br \/><span>\u00a0 add \u00a0 \u00a0DWORD PTR [ebp-0x8],0x1<\/span><br \/><span>\u00a0 cmp \u00a0 \u00a0DWORD PTR [ebp-0x8],0x31<\/span><br \/><span>\u00a0 setle \u00a0al<\/span><br \/><span>\u00a0 test \u00a0 al,al<\/span><br \/><span>\u00a0 jne \u00a0 \u00a0804840a <main+0x16><\/span><\/p>\n<p>Now for the most part they&#8217;re identical except for how we do our test to break out of the loop. \u00a0In the C version, gcc uses the <i>jle<\/i> (jump if less than or equal) instruction after the comparison (cmp) to go up and add one to <i>i<\/i> and <i>loop<\/i>. \u00a0In the C++ version, we first use <i>setle<\/i> (Set if less than or equal) to set the <i>al<\/i> register to 1 if the comparison matched. \u00a0We then test if <i>al<\/i> is true and then we \u00a0use <i>jne<\/i> to move back up in the function to do the additions. \u00a0Once loop is equal to 49, we then put 0 into the EAX register and then exit the routine.<\/p>\n<p>Until I go into WHY there&#8217;s this slight difference in output, for now let&#8217;s just say that gcc and g++ use some similar and some different code paths when generating machine code. \u00a0Have fun and Happy Father&#8217;s Day everyone.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For the first post on my new blog, I thought I&#8217;d be random and show what happens when you take the same small piece of code and compile it with both gcc and g++. \u00a0You might be surprised that, while &hellip; <a href=\"https:\/\/brian.digitalmaddox.com\/blog\/?p=21\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,9,10],"tags":[],"class_list":["post-21","post","type-post","status-publish","format-standard","hentry","category-compilers","category-g","category-gcc"],"_links":{"self":[{"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/21","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=21"}],"version-history":[{"count":0,"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/21\/revisions"}],"wp:attachment":[{"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=21"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=21"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brian.digitalmaddox.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=21"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}