• Сервис онлайн-записи на собственном Telegram-боте
    Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое расписание, но и напоминать клиентам о визитах тоже. Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.
    Для новых пользователей первый месяц бесплатно.
    Чат-бот для мастеров и специалистов, который упрощает ведение записей:
    Сам записывает клиентов и напоминает им о визите;
    Персонализирует скидки, чаевые, кэшбэк и предоплаты;
    Увеличивает доходимость и помогает больше зарабатывать;
    Начать пользоваться сервисом


  • Иллюстрированный самоучитель по Assembler

    Вызовы подпрограмм

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

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

    Подпрограмма может быть оформлена в виде процедуры, и тогда имя этой процедуры будет служить точкой входа в подпрограмму:

    drawline proc; Подпрограмма-процедура
    …; Тело подпрограммы
    ret; Команда возврата в вызывающую программу
    drawline end p
    

    С таким же успехом можно обойтись без процедуры, просто пометив первую строку программы некоторой меткой:

    drawline:; Подпрограмма, начинающаяся с метки
    …; Тело подпрограммы
    ret; Команда возврата в вызывающую программу
    …; Продолжение основной программы или
    ;другие подпрограммы
    

    В любом случае вызов подпрограммы осуществляется командой call. Подпрограмма должна завершаться командой ret, служащей для возврата управления в ту точку, откуда подпрограмма была вызвана.

    Вопросы использования подпрограмм, передачи в них параметров и возвращения результата будут рассмотрены в следующей главе. Здесь мы остановимся только на таких принципиальных архитектурных вопросах, как механизм выполнения и возможности команд call и ret. При этом надо иметь в виду, что синтаксические особенности и закономерности использования команд call и jmp во многом совпадают, и значительная часть пояснений к командам перехода справедлива и для команд вызова.

    Команда вызова подпрограммы call может использоваться в 4 разновидностях. Вызов может быть:

    • прямым ближним (в пределах текущего сегмента команд);
    • прямым дальним (в другой сегмент команд);
    • косвенным ближним (в пределах текущего сегмента команд через ячейку с адресом перехода);
    • косвенным дальним (в другой сегмент команд через ячейку с адресом перехода).

    Рассмотрим последовательно перечисленные варианты.

    Прямой ближний вызов

    Как и в случае прямого ближнего перехода, в команде прямого вызова в явной форме указывается адрес (смещение) точки входа в подпрограмму; в качестве этого адреса можно использовать как имя процедуры, так и имя метки, характеризующей точку входа в подпрограмму. В код команды, кроме кода операции E8h, входит смещение к вызываемой подпрограмме.

    В приведенном ниже примере подпрограмма оформлена в виде процедуры.

    code segment
    main proc; Основная программа
    …
    call sub; Код Е8 dddd
    …
    main endp
    sub proc near; Подпрограмма
    …
    ret; Код С3
    sub endp
    code ends
    

    Процедура-программа находится в том же сегменте команд, что и вызывающая программа. В коде команды dddd обозначает смещение в сегменте команд к точке входа в подпрограмму. При выполнении команды call процессор помещает адрес возврата (содержимое регистра IP) в стек выполняемой программы (рис. 2.16), после чего к текущему содержимому IP прибавляет dddd. В результате в IP оказывается адрес подпрограммы. Команда ret, которой заканчивается подпрограмма, выполняет обратную процедуру – извлекает из стека адрес возврата и заносит его в IP.

    Иллюстрированный самоучитель по Assembler › Основы программирования › Вызовы подпрограмм
    Рис. 2.16. Участие стека в механизме вызова ближней подпрограммы.

    Участие стека в механизме вызова подпрограммы и возврата из нее является решающим. Поскольку в стеке хранится адрес возврата, подпрограмма, сама используя стек, например, для хранения промежуточных результатов, обязана к моменту выполнения команды ret вернуть стек в исходное состояние. Команда ret, естественно, никак не анализирует состояние или содержимое стека. Она просто снимает со стека верхнее слово, считая его адресом возврата, и загружает это слово в указатель команд IP. Если к моменту выполнения команды ret указатель стека окажется смещенным в ту или иную сторону, команда ret по-прежнему будет рассматривать верхнее слово стека, как адрес возврата, и передаст по нему управление, что неминуемо приведет к краху системы.

    Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.