перевод обычной программы на c C++ на ассемблер

помогите,пожалуйста, разобрать код созданный в результате компиляции из C++ в ассемблер при помощи g++. Пытаюсь читать Брюса Эккеля. но видимо компиляторы давно шагнули вперед поэтому описание которое приведено в книге отлично от того, что получается при помощи g++. Итак, вот элементарная программа :

int foo(int i) {
    return i+1;
}


int main() {
    int y = foo(20);
}

после выполнения:

g++ -E foo.cpp -o foo.ii
g++ -S foo.ii -o foo.s

имеем вот такой ассемблерный код:

    .file   "foo.cpp"
    .text
    .globl  __Z3fooi
    .def    __Z3fooi;   .scl    2;  .type   32; .endef
__Z3fooi:
LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    movl    8(%ebp), %eax
    addl    $1, %eax
    popl    %ebp
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE0:
    .def    ___main;    .scl    2;  .type   32; .endef
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
LFB1:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    call    ___main
    movl    $20, (%esp)
    call    __Z3fooi
    movl    %eax, 28(%esp)
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE1:
    .ident  "GCC: (MinGW.org GCC Build-2) 9.2.0"

итак вот эти строки непонятны :

  1. в этой строке происходит задание параметра, верно ? :
    movl    $20, (%esp)
  1. затем вызывается моя функция, её имя тут call __Z3fooi далее переносимся в функцию , вот тут совсем ничего не понятно:
  2. зачем делать : pushl %ebp ?
  3. верно ли я понимаю, что таким образом мы заносим значение параметра в регистр esp movl %esp, %ebp ?
  4. зачем делается movl 8(%ebp), %eax ?
  5. как я понимаю addl $1, %eax это увеличивает на единицу нашу регистр ?
  6. этим восстанавливается значе popl %ebp

может быть есть где почитать статьи как передается в функцию параметры и выполняются ?


Ответы (1 шт):

Автор решения: KoVadim
movl    $20, (%esp)

esp - это указатель стека. это так изобретательно в стек заталкиваем параметр pushl %ebp

в ebp мы будем хранить указатель на стек до увеличения, но некрасиво просто так менять регистр, поэтому мы его запомним в стеке. А потом

movl %esp, %ebp

запишем esp в ebp (а предыдущее уже сохранено!)

movl    8(%ebp), %eax

а теперь берем 8 байтовое с стека - это наш параметр, который main туда положила.

addl    $1, %eax

делаем то, что нас попросили - +1

popl    %ebp

и восстановили регистр назад. Мы же его чуть выше попоритили.

а результат по соглашению возвращаем в eax - он уже там.

То есть, код делает ровно то, что его попросили.

Что бы не мучатся с ручной компиляцией, рекомендую сервис https://gcc.godbolt.org/

→ Ссылка