сборка — OSX 64 бит C ++ DIсборка построчно

Я читал следующие серии статей: http://www.altdevblogaday.com/2011/11/09/a-low-level-curriculum-for-c-and-c

Показанный дизассемблированный код и дизассемблированный код, который мне удается создать при выполнении одного и того же кода, довольно сильно различаются, и мне не хватает понимания, чтобы объяснить различия.

Есть ли кто-нибудь, кто может шаг за шагом пройти через него и, возможно, объяснить, что он делает на каждом этапе? У меня возникает ощущение, что поиски вокруг меня сделали, что первые несколько строк как-то связаны с указателями фреймов, в моем дизассемблированном коде также есть несколько дополнительных строк, которые гарантируют, что регистры пусты перед тем, как помещать в них новые значения (отсутствуют) из кода в статье)

Я запускаю это на OSX (первоначальный автор использует Windows), используя компилятор g ++ из XCode 4. Я действительно не знаю, что такое погода или нет, эти различия связаны с ОС, архитектурой (может быть, 32-разрядная или 64-разрядная?) или сам компилятор. Это может быть даже код, который я предполагаю — мой обернут в объявление основной функции, тогда как оригинальный код не упоминает об этом.

Мой код:

int main(int argc, const char * argv[])
{

int x = 1;
int y = 2;
int z = 0;

z = x + y;

}

Мой разобранный код:

0x100000f40:  pushq  %rbp
0x100000f41:  movq   %rsp, %rbp
0x100000f44:  movl   $0, %eax
0x100000f49:  movl   %edi, -4(%rbp)
0x100000f4c:  movq   %rsi, -16(%rbp)
0x100000f50:  movl   $1, -20(%rbp)
0x100000f57:  movl   $2, -24(%rbp)
0x100000f5e:  movl   $0, -28(%rbp)
0x100000f65:  movl   -20(%rbp), %edi
0x100000f68:  addl   -24(%rbp), %edi
0x100000f6b:  movl   %edi, -28(%rbp)
0x100000f6e:  popq   %rbp
0x100000f6f:  ret

Разобранный код из оригинальной статьи:

mov    dword ptr [ebp-8],1
mov    dword ptr [ebp-14h],2
mov    dword ptr [ebp-20h],0
mov    eax, dword ptr [ebp-8]
add    eax, dword ptr [ebp-14h]
mov    dword ptr [ebp-20h],eax

Полная разбивка строк за строкой была бы чрезвычайно полезной, но любая помощь в понимании этого была бы признательна.

0

Решение

Есть два основных различия между вашим разобранным кодом и кодом статьи.

Во-первых, в статье используется синтаксис Intel для ассемблера, а в разобранном коде — традиционный Unix / AT.&Синтаксис T ассемблера. Некоторые различия между ними описаны на Википедия.

Другое отличие состоит в том, что в статье пропущен пролог функции, который устанавливает кадр стека, и эпилог функции, который разрушает кадр стека и возвращает его вызывающей стороне. Программа, которую он разбирает, должна содержать инструкции, чтобы сделать эти вещи, но его дизассемблер не показывает их. (На самом деле кадр стека мог и, вероятно, будет опущен, если оптимизатор был включен, но он явно не включен.)

Есть также некоторые незначительные отличия: ваш код использует немного другое расположение для локальных переменных, а ваш код вычисляет сумму в другом регистре.

На Mac g ++ не поддерживает использование мнемоники Intel, но clang поддерживает:

:; clang -S -mllvm --x86-asm-syntax=intel t.c
:; cat t.s
.section    __TEXT,__text,regular,pure_instructions
.globl  _main
.align  4, 0x90
_main:                                  ## @main
.cfi_startproc
## BB#0:
push    RBP
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset rbp, -16
mov RBP, RSP
Ltmp4:
.cfi_def_cfa_register rbp
mov EAX, 0
mov DWORD PTR [RBP - 4], EDI
mov QWORD PTR [RBP - 16], RSI
mov DWORD PTR [RBP - 20], 1
mov DWORD PTR [RBP - 24], 2
mov DWORD PTR [RBP - 28], 0
mov EDI, DWORD PTR [RBP - 20]
add EDI, DWORD PTR [RBP - 24]
mov DWORD PTR [RBP - 28], EDI
pop RBP
ret
.cfi_endproc.subsections_via_symbols

Если вы добавите -g флаг, компилятор будет добавлять отладочную информацию, включая имена файлов источника и номера строк. Он слишком велик, чтобы поместить его целиком, но это важная часть:

    .loc    1 4 14 prologue_end     ## t.c:4:14
Ltmp5:
mov DWORD PTR [RBP - 20], 1
.loc    1 5 14                  ## t.c:5:14
mov DWORD PTR [RBP - 24], 2
.loc    1 6 14                  ## t.c:6:14
mov DWORD PTR [RBP - 28], 0
.loc    1 8 5                   ## t.c:8:5
mov EDI, DWORD PTR [RBP - 20]
add EDI, DWORD PTR [RBP - 24]
mov DWORD PTR [RBP - 28], EDI
0

Другие решения

Весь код из исходной статьи находится в вашем коде, вокруг него есть только некоторые дополнительные вещи. Это:

0x100000f50:  movl   $1, -20(%rbp)
0x100000f57:  movl   $2, -24(%rbp)
0x100000f5e:  movl   $0, -28(%rbp)
0x100000f65:  movl   -20(%rbp), %edi
0x100000f68:  addl   -24(%rbp), %edi
0x100000f6b:  movl   %edi, -28(%rbp)

Соответствует непосредственно 6 инструкциям, о которых говорилось в статье.

2

Прежде всего, ассемблер, указанный как «из оригинальной статьи», использует синтаксис «Intel», где «дизассемблированный вывод» в вашем посте — «AT».&Синтаксис T «. Это объясняет порядок аргументов в инструкциях» задом наперед «[давайте не будем спорить о том, что правильно или неправильно, хорошо?], А имена регистров начинаются с префикса %константы с префиксом $, Существует также разница в том, как ссылки / смещения памяти на регистры ссылаются — dword ptr [reg+offs] в Intel ассемблер переводится как l в качестве суффикса к инструкции, и offs(%reg),

32-битные и 64-битные переименовывают некоторые регистры — %rbp такой же как ebp в коде статьи.

Фактические смещения (например, -20) различаются отчасти потому, что регистры больше в 64-битных, но и потому, что у вас есть argc а также argv как часть аргументов вашей функции, которая хранится как часть запуска функции — у меня такое ощущение, что оригинальная статья фактически разбирает другую функцию, чем main,

0
По вопросам рекламы [email protected]