В своем изучении ассемблера, я немного отклонился от линии начертанной великим Питерем Аблем, но я думаю он на меня не обидется :) Еще немного поэкспериментируем со стеком и подпрограммами. Немного практики ни когда не повредит, а потом вернемся к генеральной линии партии... ммм.... вернее Питера.... Абеля....
Итак, наша програ продолжает мутировать:

Оператор
CALL вызывает подпрограмму subp, которую мы определили с помощью соответствующих директив
PROC и
ENDP. Оператор
RET осуществляет возврат из подпрограммы в головную программу.
Взглянем на листинг:

Внимательно медитируем на листинг...
Команда
call subp имеет машинный код
E80005, где собственно
E8 – это сама команда, а
0005 – это смещение, указывающее на первую команду нашей подпрограммы. Команда
call уменьшает значение SP на два, помещает в стек адрес, следующей за ней команды (в нашем случае адрес команды
mov ax,4c00h равный
000F). Затем вычисляет адрес команды подпрограммы, на которую надо передать управление, прибавляя к адресу следующей за ней команды смещение (положительное или отрицательное) равное количеству байт программы, до первой команды вызываемой подпрограммы – в нашем случае 5 байт (
000F+5=0014) и помещает это число (в нашем случае
0014) в регистр IP, передавая таким образом управление на подпрограмму. Подпрограмма выполняется до команды
RET, которая извлекает из стека адрес возврата из подпрограммы (в нашем случае
000F) и помещает его в регистр IP (передавая, таким образом, управление вызвавшей ее программе) и уменьшает значение SP на два.
И, традиционно, помедитируем на код сгенерированный ассемблером:

Посмотреть на программу в hiew, так же не повредит:

Ну и, святое дело, дебагер:

Скриншот сделан еще до выполнения первой команды. Внимательно медитируем и жмем пять раз F8, то есть останавливаемся на команде call (ее не выполняем).

Из скриншота видно, что отладчик не плохо поорудовал в стеке, но при этом значение регистра SP осталось прежним, и он по прежнему указывает на дно стека (вернее на первое слово под ним). Делаем выводы и далее жмем
один раз F7, чтобы войти в подпрограмму.

Как, уже говорилось, команда
call уменьшила содержимое регистра
SP на два (
0040-2=003E), поместила в стек адрес следующей за ней команды
(000F), прибавила к адресу следующей за ней команды смещение до первой исполняемой команды подпрограммы (
000F+5=14h) и поместила это значение (
14h) в регистр
IP.
Далее жмем
два раза F8.

Команда
ret, извлекла из стека адрес возврата из подпрограммы (
000F) и поместила его в регистр IP, а затем увеличила значение регистра SP на два, вернув указатель стека, опять на его дно.
Ну и покажем вывод нашей мега программы. Она два раза выводит знаменитую фразочку, но без перевода каретки на новую строку (так как мы это не запрограммировали.
C:\ASM\HELLO\TASM>hello8-=* Hello World *=--=* Hello World *=-C:\ASM\HELLO\TASM>
Комментариев нет:
Отправить комментарий