Разница между JUMP и CALL - PullRequest
21 голосов
/ 07 февраля 2009

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

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

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

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

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

Ответы [ 5 ]

23 голосов
/ 07 февраля 2009

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

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

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

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

вместо CALL.

1 голос
/ 07 февраля 2009

Вы совершенно правы относительно разницы между прыжком и вызовом.

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

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

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

0 голосов
/ 18 августа 2013

Одна поправка к вашим мыслям: не только с tail recursion , но обычно с tail Calls , что нам не нужен стек стека и, следовательно, просто может JMP там (при условии, что аргументы были установлены правильно).

0 голосов
/ 18 августа 2013

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

0 голосов
/ 07 февраля 2009

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

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

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

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

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

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

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

...