Почему он показывает puts при дизассемблировании, независимо от того, использую ли я printf или puts?

Я новичок в программировании и хотел спросить, почему я получаю тот же результат с другим кодом. На самом деле я читаю книгу, и пример в книге с printf (также на ассемблере). В этом случае он говорит <printf@plt>. Код ассемблера в книге отличается от моего, но код C тот же. Мой процессор просто вычисляет по-другому?

(Проблема при вызове <+34> <puts@plt>)

Код 1:

#include <stdio.h>

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

Код 2:

#include <stdio.h>

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

Код 1 в разобранном виде:

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.

Код 2 в разобранном виде:

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.

person l1on_coding    schedule 28.12.2016    source источник
comment
GNU gcc считает хорошей идеей заменить printf("some string\n") на puts("some string"); — так оно и есть. Это оптимизация; puts() не нужно интерпретировать строку формата.   -  person Jonathan Leffler    schedule 29.12.2016
comment
Связанный: Может ли printf автоматически заменяться на puts в C программа?   -  person Alexander O'Mara    schedule 29.12.2016
comment
Ок спасибо за помощь! :)   -  person l1on_coding    schedule 29.12.2016
comment
Имейте в виду, что компиляторы могут изменять и заменять любую из стандартной библиотеки C. Например, обычно переписывают функции памяти и строк, такие как memset, memcpy и strlen.   -  person Zan Lynx    schedule 29.12.2016
comment
Другой вопрос/ответ, который может быть полезен: stackoverflow.com/questions/37435984/   -  person Michael Petch    schedule 29.12.2016
comment
Это интересно, я бы не догадался, что gcc сделает эту оптимизацию на -O0. (Но обратите внимание, что gcc -O0 не означает буквальный перевод исходного кода в asm: title="отключить все параметры оптимизации в gcc">stackoverflow.com/questions/33278757/)   -  person Peter Cordes    schedule 29.12.2016


Ответы (1)


Функция puts предпочтительнее, потому что она проще как по функциональности (без декодирования строки формата), так и по передаче аргументов.

Например, соглашения о вызовах System V ABI x86 требуют установки количества аргументов XMM (YMM) (printf является вариативным) в RAX. puts проще, так как с RDI передается только один аргумент.

person Grzegorz Szpetkowski    schedule 28.12.2016