Где корреляция один к одному между сборкой и кодом cpp? - PullRequest
2 голосов
/ 24 февраля 2012

Я попытался проверить, как этот код будет в сборке:

int main(){
  if (0){
    int x = 2;
    x++;
  }
  return 0;
}

Мне было интересно, что означает if (0)?

Я использовал команду оболочки g++ -S helloWorld.cpp в Linux

и получил этот код:

    .file   "helloWorld.cpp"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1"
    .section    .note.GNU-stack,"",@progbits
  1. Я ожидал, что сборка будет содержать JZ, но где она?
  2. Как я могу скомпилировать код без оптимизации?

Ответы [ 6 ]

6 голосов
/ 24 февраля 2012

Нет прямой, гарантированной связи между исходным кодом C ++ и сгенерированным ассемблером.Исходный код C ++ определяет определенную семантику, и компилятор выводит машинный код, который будет реализовывать наблюдаемое поведение этой семантики.То, как компилятор делает это, и фактический код, который он выводит, может сильно различаться даже на одном и том же оборудовании;Я был бы очень разочарован компилятором, который генерировал код, который сравнивал 0 с 0, а затем делал условный переход, если результаты были равны, независимо от того, какой исходный код C ++.

В вашемНапример, единственным наблюдаемым поведением в вашем коде является возврат 0 в ОС.Все, что генерирует компилятор, должно делать это (и не иметь другого наблюдаемого поведения).Код, который вы показываете, не является оптимальным для этого:

xorl %eax, %eax
ret

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

Что касается оптимизации, это зависит от компилятора.С g ++ -O0 (это буква O, за которой следует число ноль) отключает всю оптимизацию.Это по умолчанию, однако, так что это действительно то, что вы видите.Помимо нескольких разных уровней оптимизации, g ++ поддерживает включение или отключение отдельных оптимизаций.Возможно, вы захотите взглянуть на полный список: http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Optimize-Options.html#Optimize-Options.

5 голосов
/ 24 февраля 2012

Компилятор исключает этот код как мертвый код, например код, который никогда не будет работать. Осталось установить кадр стека и значение, возвращаемое функцией. if(0) никогда не бывает правдой, в конце концов. Если вы хотите получить JZ, то вам, вероятно, следует сделать что-то вроде if(variable == 0). Имейте в виду, что компилятор никоим образом не обязан фактически выдавать инструкцию JZ, он может использовать любые другие средства для достижения того же самого. Компиляция языка высокого уровня в ассемблер очень редко является четким соотношением один к одному.

1 голос
/ 24 февраля 2012

Код, вероятно, был оптимизирован.

if (0){
   int x = 2;
  x++;
}

было устранено.

movl $0, %eax - это то место, где было установлено возвращаемое значение. Кажется, что другие инструкции - это только инициализация и выход из программы.

0 голосов
/ 24 февраля 2012

блок if (0) {} оптимизирован компилятором, так как он никогда не будет вызван. так что ваша функция возвращает только 0 (movl $ 0,% eax)

0 голосов
/ 24 февраля 2012

Оптимизатор удалил условный оператор if и весь код внутри, так что он вообще не отображается.

0 голосов
/ 24 февраля 2012

Существует вероятность того, что компилятор оптимизировал его, поскольку это никогда не соответствует действительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...