Как процессор обрабатывает условия?

В Java есть функции, например, для форматирования, заполненного нулями; с соответствующим названием String.format, который может сделать это для вас. Например,

int minutes = 0, seconds = 0;
String timerString = String.format("%02d:%02d", minutes, seconds);
System.out.println(timerString);

, который заполняет ноль, вышеупомянутые выходы

00:00
5
задан UnkwnTech 25 March 2009 в 19:48
поделиться

7 ответов

Процессор имеет "Ответвление, если" инструкции, что, когда определенное условие соблюдено, это переходит, и иначе это продвигается к следующей инструкции.

Так

if(A)
{
    dosomething;
}

стал бы

load A into register 0
if the zero flag is set (ie, register 0 contains 0x00) then jump to endcondition)
dosomething
endcondition:

Более сложные условия ( if(A || B && C) ) станьте последовательностью инструкций, которая оставляет регистр в 0 или не нулевом состоянии, таким образом, branchif инструкция может перейти или не перейти на основе условных флагов.

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

Как мокко указывает в комментариях, некоторая архитектура позволяет Вам применять условное выражение к некоторым, многим или даже всем инструкциям, таким образом, у Вас могло бы не только быть 'ответвление, если' инструкции, но также и 'и если', 'добавляют если', 'перемещаются если' и т.д.

x86 очень, очень, очень сложен вне этого простого объяснения, после того как Вы входите в конвейерную обработку, исполнение с изменением последовательности, кэширование, микрокод и все другие усовершенствованные темы. В большинстве целей вышеупомянутое объяснение достаточно. Если Вы пишете ручной работы очень, очень туго натянутый алгоритм, тем не менее, необходимо будет принять эти вещи во внимание для максимальной производительности и пропускной способности.

Это - тема для другого вопроса хотя...

- Adam

13
ответ дан 18 December 2019 в 07:56
поделиться

Это довольно просто в использовании вывод компилятора C (используйте -S включите gcc) видеть, что производит данный отрывок C, генерирует при компиляции. Будьте осторожны при использовании оптимизации на игрушечных программах все же. Если Вы не будете осторожны, то оптимизатор будет часто оптимизировать далеко условные выражения, которые будут всегда идти так или иначе (см. эту статью о микросравнительных тестах для более подробного объяснения).

Например, тривиальная программа C:

#include <stdio.h>

int main (int argc, char **argv) {
    int ii = 10;
    int jj = 20;
    if (jj > ii) {
        puts ("jj > ii \n");
    }
    return 0;
}

компиляции к следующему ассемблеру:

    .file   "foo.c"
    .section    .rodata
.LC0:
    .string "jj > ii \n"
    .text
.globl main
    .type   main, @function
main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $20, %esp
    movl    $10, -8(%ebp)
    movl    $20, -12(%ebp)
    movl    -12(%ebp), %eax
    cmpl    -8(%ebp), %eax
    jle .L2
    movl    $.LC0, (%esp)
    call    puts
.L2:
    movl    $0, %eax
    addl    $20, %esp
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.3.2-1ubuntu12) 4.3.2"
    .section    .note.GNU-stack,"",@progbits

Для краткого рассечения того, что продолжается:

  • Первый раздел (.rodata) объявляет константу со строкой'jj > ii \n')

  • Второй раздел инициализирует содержание ii и jj переменные на стеке.

  • Бит от cmpl -8(%ebp), %eax делает фактическое сравнение; jle инструкция перескакивает через вызов к'puts', который является эффективно логикой'if'оператор инвертируется.

  • После маркировки'.L2'система убирает вершину стека и возвращается из вызова.

5
ответ дан 18 December 2019 в 07:56
поделиться

Это - команда перехода, зависящая от определенной архитектуры машины. Это выясняет, как создать ячейку памяти или регистр для тестирования на определенное условие низкого уровня - как branch-if-not-equal, или branch-if-not-zero... - делает тот тест, затем переходит (или не делает, если условие перестало работать) к другой части памяти. Очевидно, если у Вас есть сложное условие, оно, возможно, должно сделать, оценивают много различных условий и может включить несколько команд перехода.

2
ответ дан 18 December 2019 в 07:56
поделиться

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

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

Один код операции (на самом деле существуют, вероятно, несколько), однако позволяет CPU "Переходить" путем "сравнения" значений в двух других регистрах CPU, и если Вы больше, чем другой, он копирует один адрес памяти в регистр команд, тогда как, если другой является самым большим, он копирует второй, другой адрес памяти в регистр команд.

Это - почти так "низкий" уровень, как он может быть помещен это w/o, говорящий о реле и транзисторах...

1
ответ дан 18 December 2019 в 07:56
поделиться

В основном у Вас есть группа электронов, раздаваемая среди различных атомов в Вашем ЦП. Из-за структуры кремниевых атомов в Вашем ЦП электроны следуют за определенными путями, которые определяют ответвление выполнения, за которым будет следовать компьютер.

Править: Кажется, что я должен объяснить немного менее неопределенно. Терпите меня, я специализировался в информатике, не электротехнике, таким образом, у меня нет очень глубокого понимания этих вещей:

Ваш ЦП сделан из материал, обычно кремний, который называют "полупроводником". Одна из больших вещей о полупроводниках - то, что их elecrical свойства могут легко варьироваться посредством "легирования" или применения примесей, которые создают области отрицательных или положительных "носителей заряда" на материале. Строки, где эти области объединяются, известны как "соединения", и электричество течет намного более легко один путь через эти соединения, чем другой. Это свойство используется для создания диодов, которые позволяют электричеству течь только в одном направлении и транзисторах, которые могут считаться крошечными переключателями, которые позволяют одному электрическому току управлять другим электрическим током. Эти транзисторы и диоды объединены в несметном числе способов создать логические элементы Вашего ЦП.

Многие логические элементы в Вашем ЦП выделены тому, чтобы быть "блоком управления", который отвечает за получение и декодирование инструкций, сообщение остальной части ЦП, что сделать, и наконец получение следующей инструкции. На x86 блок управления на самом деле выполняет "микрокод", который говорит его, как иметь дело с ветвлением, конвейерной обработкой, и так далее. Действительно необходимо быть невероятно конкретны относительно конкретной строки процессоров, чтобы войти, как x86 ISA реализован на конкретной микроархитектуре.

-1
ответ дан 18 December 2019 в 07:56
поделиться

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

Например, код:

int x;

if ( y < 5 )
  x = 5;
else
  x = y;

может быть скомпилирован, как будто это было записано:

y -= 5
int r = y < 0; // r is 1 if y < 5, 0 otherwise
r -= 1         // r is 0x00000000 if y < 5, 0xffffffff otherwise
x = y & r      // x is 0 if y < 5, (y-5) otherwise 
x += 5;        // x is 5 if y < 5, y otherwise

который может быть преобразован в машинный код без любых ответвлений

0
ответ дан 18 December 2019 в 07:56
поделиться

Вот довольно хороший обзор того, как такие структуры могли бы скомпилировать на x86 архитектуре: http://en.wikibooks.org/wiki/X86_Disassembly/Branches#If-Then

Существуют способы иногда избежать ответвления (который часто имеет решительно отрицательные последствия производительности, должные конвейерно обрабатывать повреждение). Например, i686 система команд вперед (все от Pentium Pro до текущего дня) имеет условную команду перемещения, которая могла бы скомпилировать это:

if (a==0) {
    b= 1;
}

к чему-то вроде этого:

cmp    0, eax
cmovzl ebx, 1

без ответвления пока Ваш компилятор настраивается для предназначения для i686 + (и похоже на него; компиляторы являются сложными и непостижимыми). НАБОР [условие] является другим, подобной, условной инструкцией.

Удачливые старые программисты ARM добираются для определения любой инструкции условно, которая сокращает ответвления много.

0
ответ дан 18 December 2019 в 07:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: