Почему регистр и стек% al были изменены перед вызовом сборки printf x86 из программы C "Hello World", скомпилированной gcc - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь лучше понять компиляторы и сборку и в настоящее время пытаюсь понять, почему эта простая программа «Hello, World» изменяет стек и регистры% al перед вызовом printf.

Это сборка, сгенерированная gcc с отключенной оптимизацией (некоторые директивы компилятора были удалены):

_main:                                  ## @main
    .cfi_startproc
## %bb.0:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    leaq    L_.str(%rip), %rdi
    movl    $0, -4(%rbp)
    movb    $0, %al
    callq   _printf
    xorl    %ecx, %ecx
    movl    %eax, -8(%rbp)          ## 4-byte Spill
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc
                                        ## -- End function
    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
    .asciz  "Hello, World!\n"

А вот (чрезвычайно простая) программа на C:

#include <stdio.h>

int main() {
  printf("Hello, World!\n");
  return 0;
}

Мне интересно, что конкретно происходит в двух строках, предшествующих инструкции "call _printf". Кажется, что часть стека обнуляется, а также регистр% al, но я не знаю почему.

Меня также смущает, почему регистр% ecx очищается и заполняется содержимым% eax, которое, я полагаю, является возвращаемым значением из printf перед возвратом.

Заранее спасибо за любую помощь.

1 Ответ

0 голосов
/ 12 января 2019

Сброс %ecx и передача его в %eax просто гарантирует, что основная функция возвращает 0. Непосредственно перед этим, возвращаемое значение функции _printf копируется из %eax в кадр стека с помощью movl %eax, -8(%rbp) , но это значение просто отбрасывается, когда стек начинает освобождать кадр с помощью инструкции addq $16, %rsp.

...