Подтвердить что ты не робот

Разница между JUMP и CALL

Как отличается инструкция JUMP и CALL? Как это связано с концепциями более высокого уровня, такими как GOTO или вызов процедуры? (Правильно ли я в сравнении?)

Вот что я думаю:

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

С другой стороны, вызов CALL или процедуры/функции возвращается в точку, из которой он вызывается. Из-за этой разницы в их характере языки обычно используют стек, а кадр стека толкается, чтобы "запомнить" место для возврата для каждой вызванной процедуры. Это относится и к рекурсивным процедурам. В случае хвостовой рекурсии, однако, нет необходимости "нажимать" кадр стека для каждого вызова.

Ваши ответы и комментарии будут высоко оценены.

4b9b3361

Ответ 1

В основном вы правы, если вы говорите о CALL/JMP в сборке x86 или что-то подобное. Основное отличие:

  • JMP выполняет переход к местоположению без каких-либо действий
  • CALL выталкивает текущий указатель инструкции в стеке (скорее: один после текущей команды), а затем JMP в местоположение. С помощью RET вы можете вернуться туда, где вы были.

Обычно CALL - это просто функция удобства, реализованная с использованием JMP. Вы могли бы сделать что-то вроде

          movl $afterJmp, -(%esp)
          jmp location
afterJmp:

вместо CALL.

Ответ 2

Вы точно знаете разницу между прыжком и вызовом.

В примере с одной функцией с хвостовой рекурсией компилятор может повторно использовать существующий фрейм стека. Однако он может усложниться с помощью взаимно рекурсивных функций:

void ping() { printf("ping\n"); pong(); }
void pong() { printf("pong\n"); ping(); }

Рассмотрим случай, когда ping() и pong() являются более сложными функциями, которые принимают различное количество параметров. Документ Марка Пробста подробно рассказывает о реализации хвостовой рекурсии для GCC.

Ответ 3

Думаю, у вас есть общая идея.

Это зависит от архитектуры, но в целом на аппаратном уровне:

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

  • Команда вызова выведет текущее местоположение программы (или текущее местоположение + 1) в стек вызовов и перейдет к другому частью программы. После этого команда возврата выведет местоположение из стека вызовов и вернется в исходное местоположение (или местоположение orignal + 1).

Итак, команда перехода близка к GOTO, а команда вызова близка к процедурно-функциональному вызову.

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

При сборе сборки мне легче справляться с RISC, чем процессоры x86, поскольку имеет тенденцию иметь меньше инструкций и более простые операции.

Ответ 4

Одна поправка к вашим мыслям: это не только с хвостовой рекурсией, но, как правило, с хвостовыми вызовами, нам не нужен фрейм стека, и, следовательно, просто JMP там (если аргументы настроены правильно).

Ответ 5

В соответствии с микропроцессором, во-первых, условие проверяется, а затем выполняет операции перехода (переходит к другому коду) и не возвращается. Операция вызова похожа на функцию callig на языке c, и когда функция выполняется, она возвращается обратно, чтобы завершить ее выполнение.