Вы, кажется, говорили о подпрограммах, так вот подноготная на этом.
Когда вы вызов подпрограммой, это выглядит примерно так (адреса будут отличаться друг от друга, но я не хочу, чтобы запутать вас с указанием переменной длины):
1234 call 8888
1235 <next instruction>
Что происходит, что call
сначала помещает следующий указатель инструкции 1235
в стек (структура данных с последним в первом порядке), а затем устанавливает указатель на то, что вы вызываете, 8888
в этом случае.
Позже, возврат производится в 8889
:
8888 mov eax, 0
8889 ret
Что возвращение делает это просто поп первое значение из стека (т.е. 1235
, который был выдвинут призыв) и загружает его в указатель инструкции. Так что это не возвращение, рассказывающее вам, куда идти, это информация, которая была нажата на стек по вызову .
Если вы имели jmp
инструкцию в конце вашей подпрограммы, было бы только смог вернуться в одну точку в коде (дисконтирование все замечательные вещи, которые вы могли бы сделать с другими режимами адресации на данный момент):
8889 jmp 1235
Используя возврат, вы возвращаетесь туда, куда бы вы ни пришли, независимо от того, где это было.
Ассемблер для бесконечного цикла может быть простым, как:
loopy:
jmp loopy
Что касается регистров, eax
, ebx
, ecx
и edx
рассматриваются регистры общего назначения. Это отличает их от регистров особого назначения, таких как указатель стека, указатель базы, указатели источника и адресата и т. Д., Которые имеют специализированные инструкции в зависимости от их использования.
ax
, возможно, имел некоторые дополнительные полномочия в очень ранних итерациях архитектуры x86, но я не уверен, что это все еще так. Если вы кодируете свои собственные материалы, вы должны в основном использовать их взаимозаменяемо. Если вы следуете API или ABI, вам необходимо следовать правилам, которые он налагает (например, интерфейс системного вызова Linux, где eax
содержит номер системного вызова).
Спасибо за ваш быстрый ответ, я понимаю сейчас. – Imaginarys