Сборка: почему переход к метке, возвращаемой через ret, вызывает ошибку сегментации?

В руководстве по сборке Linux говорится:

следует запомнить одну очень важную вещь: если вы планируете вернуться из процедуры (с помощью инструкции RET), не переходите к ней! Как в "никогда!" Это вызовет ошибку сегментации в Linux (что нормально - все, что делает ваша программа, это завершается), но в DOS это может взорваться вам прямо в лицо с разной степенью ужасности.

Но я не могу понять, почему вызывает ошибку сегментации. это похоже на возвращение из функции.

У меня есть ситуация, когда мне нужно реализовать логику «Если X произойдет, вызовите процедуру A. В противном случае вызовите процедуру B.» Есть ли другой способ, кроме как прыгать, как кенгуру, плетущий спагетти-код?


person InvalidBrainException    schedule 23.03.2012    source источник
comment
Просто примечание: ничто не мешает вам это делать, но то, что он делает, не всегда очевидно для начинающих программистов на ассемблере. Наиболее частый случай этого называется хвостовой вызов, и он распространен в функциональных языках. Эффект состоит в том, чтобы вернуться к вызывающей функции, содержащей прыжок (минуя остальную часть этой функции), если вы очистили свою маленькую часть стека. Если вы этого не сделали, тогда вы увидите ошибки сегментации.   -  person cHao    schedule 24.03.2012
comment
Убедитесь, что вы понимаете разницу между jmp и call.   -  person Gunther Piez    schedule 24.03.2012


Ответы (2)


Потому что CALL помещает текущий адрес инструкции в стек, а RET снимает его, чтобы вернуться на сайт вызова. JMP (и соответствующие инструкции) ничего не помещают в стек.

person Oliver Charlesworth    schedule 23.03.2012

Я думаю, что этот совет может иметь отношение к конвейеру, но я не уверен.

Я считаю, что вы задаете следующий вопрос:

... subroutine entrypoint ...
... various instructions in a routine ...
jmp label
... move instructions in a routine...
label:
ret

В чем проблема, если есть, с этим? Во-первых, я не уверен, что это вообще проблема. Но если это так, то это трубопровод. На некоторых процессорах одна или несколько инструкций после jmp будут выполнены до того, как управление перейдет к метке.

В большинстве случаев я боюсь, что вы неправильно поняли то, что прочитали, или я неправильно понял то, что вы написали. jmp-переход от одной точки подпрограммы к инструкции ret должен быть нормальным. jmp-ing вместо выполнения ret, как отмечали другие люди, является глупой идеей.

person bmargulies    schedule 23.03.2012
comment
Я думаю, что вопрос относится к тому, почему вы не можете использовать наивный jmp для вызова функции вместо использования инструкции call. Конечно, вы можете, если сами настроите стек, но в противном случае это обречено на неудачу, потому что ret вернется в никуда. - person Niklas B.; 24.03.2012
comment
Я думаю, что цитата OP означает, что не переходите к подпрограмме, всегда вызывайте ее, а не переходите к инструкции ret. - person Oliver Charlesworth; 24.03.2012