2

I'm pretty new to programming and wanted to ask why I get the same result with different code. I'm actually reading a book and the example in the book is with printf (also in Assembler). In this case it says <printf@plt>. The assembler code in the book differs from mine but C Code is the same. Is my processor just computing different?

(Problem is at call <+34> <puts@plt>)

Code 1:

#include <stdio.h>

int main()
{
    int i;
    for(i=0; i<10; i++)
    {
        printf("Hello, world!\n");
    }
    return 0;
}

Code 2:

#include <stdio.h>

int main()
{
    int i;
    for(i=0; i<10; i++)
    {
        puts("Hello, world!\n");
    }
    return 0;
}

Code 1 disassembled:

Dump of assembler code for function main:
   0x080483eb <+0>: lea    ecx,[esp+0x4]
   0x080483ef <+4>: and    esp,0xfffffff0
   0x080483f2 <+7>: push   DWORD PTR [ecx-0x4]
   0x080483f5 <+10>:    push   ebp
   0x080483f6 <+11>:    mov    ebp,esp
   0x080483f8 <+13>:    push   ecx
=> 0x080483f9 <+14>:    sub    esp,0x14
   0x080483fc <+17>:    mov    DWORD PTR [ebp-0xc],0x0
   0x08048403 <+24>:    jmp    0x8048419 <main+46>
   0x08048405 <+26>:    sub    esp,0xc
   0x08048408 <+29>:    push   0x80484b0
   0x0804840d <+34>:    call   0x80482c0 <puts@plt>
   0x08048412 <+39>:    add    esp,0x10
   0x08048415 <+42>:    add    DWORD PTR [ebp-0xc],0x1
   0x08048419 <+46>:    cmp    DWORD PTR [ebp-0xc],0x9
   0x0804841d <+50>:    jle    0x8048405 <main+26>
   0x0804841f <+52>:    mov    eax,0x0
   0x08048424 <+57>:    mov    ecx,DWORD PTR [ebp-0x4]
   0x08048427 <+60>:    leave  
   0x08048428 <+61>:    lea    esp,[ecx-0x4]
   0x0804842b <+64>:    ret    
End of assembler dump.

Code 2 disassembled:

Dump of assembler code for function main:
   0x080483eb <+0>: lea    ecx,[esp+0x4]
   0x080483ef <+4>: and    esp,0xfffffff0
   0x080483f2 <+7>: push   DWORD PTR [ecx-0x4]
   0x080483f5 <+10>:    push   ebp
   0x080483f6 <+11>:    mov    ebp,esp
   0x080483f8 <+13>:    push   ecx
   0x080483f9 <+14>:    sub    esp,0x14
   0x080483fc <+17>:    mov    DWORD PTR [ebp-0xc],0x0
   0x08048403 <+24>:    jmp    0x8048419 <main+46>
=> 0x08048405 <+26>:    sub    esp,0xc
   0x08048408 <+29>:    push   0x80484b0
   0x0804840d <+34>:    call   0x80482c0 <puts@plt>
   0x08048412 <+39>:    add    esp,0x10
   0x08048415 <+42>:    add    DWORD PTR [ebp-0xc],0x1
   0x08048419 <+46>:    cmp    DWORD PTR [ebp-0xc],0x9
   0x0804841d <+50>:    jle    0x8048405 <main+26>
   0x0804841f <+52>:    mov    eax,0x0
   0x08048424 <+57>:    mov    ecx,DWORD PTR [ebp-0x4]
   0x08048427 <+60>:    leave  
   0x08048428 <+61>:    lea    esp,[ecx-0x4]
   0x0804842b <+64>:    ret    
End of assembler dump.
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 4
    GNU `gcc` thinks it is a good idea to replace `printf("some string\n")` with `puts("some string");` — so it does. It's an optimization; `puts()` doesn't have to interpret the format string. – Jonathan Leffler Dec 28 '16 at 23:13
  • 1
    Related: [Can printf get replaced by puts automatically in a C program?](https://stackoverflow.com/questions/25816659/can-printf-get-replaced-by-puts-automatically-in-a-c-program) – Alexander O'Mara Dec 28 '16 at 23:15
  • Ok thanks for help! :) – l1on_coding Dec 28 '16 at 23:19
  • Be aware that compilers can modify and replace *any* of the standard C library. It's common to rewrite the memory and string functions like `memset`, `memcpy` and `strlen` for example. – Zan Lynx Dec 28 '16 at 23:46
  • Another question/answer that may be of value: http://stackoverflow.com/questions/37435984/why-doesnt-gcc-optimize-this-call-to-printf – Michael Petch Dec 29 '16 at 00:03
  • 1
    That's interesting, I wouldn't have guessed that gcc would do this optimization at `-O0`. (But note that `gcc -O0` doesn't mean literal braindead translation of source to asm: http://stackoverflow.com/questions/33278757/disable-all-optimization-options-in-gcc/33284629#33284629) – Peter Cordes Dec 29 '16 at 02:25

1 Answers1

2

The puts function is preferred because it is simpler to in both functionality (no format string decoding) and argument passing.

For instance, System V ABI x86 calling conventions require to set number of XMM (YMM) arguments (printf is variadic) in RAX. puts is easier, as there is only single argument passed with RDI.

Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137