Операции со стеком



Операции со стеком


    В гл.3 обсуждалось, как реализован стек в микропроцессоре 8088.
    Микропроцессор 8088 адресует стек с помощью регистровой пары SS:SP.
    Помещение объектов в стек приводит к тому, что он растет в сторону
    меньших адресов памяти.  Стек, кроме всего прочего, служит и для
    запоминания адресов возврата из подпрограмм.  В этом разделе
    рассматриваются некоторые команды, которые непосредственно работают
    со стеком.
 
      Фиг.4.7 иллюстрирует ассемблированные стековые команды.
    Мнемоника команд очевидна; за кодами операций PUSH и POP следует
    имя регистра для указания операнда. Единственным исключением
    является помещение и извлечение из стека регистра флагов, которые
    используют мнемонику PUSHF и POPF соответственно. Содержимое любой
    ячейки памяти, которую программа может адресовать, используя
    возможные способы адресации, также может быть помещено или
    извлечено из стека.
 
      При любых действиях со стеком в микропроцессоре 8088 базовой
    единицей информации является 16=битовое слово. Длина любого
    объекта, помещаемого в стек либо извлекаемого из стека, составляет
    одно или несколько слов. Байтовых команд, связанных с засылкой
    данных или извлечением их из стека, не существует. Если, например,
    программе необходимо сохранить содержимое регистра AL а стеке, она
    должна поместить содержимое регистра AX, так как не существует
    способа сохранения только содержимого регистра AL.
 
      Основное назначение стека - временное хранение информации. Как
    мы уже видели, стек используется для сохранения адреса возврата;
    программа также может сохранять данные. Если программа хочет
    использовать регистр, пусть даже сохранить текущие данные, она
    может послать значение этого регистра в стек. Эти данные
    сохраняются в стеке и позже могут быть восстановлены. Например,
           Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:00:43
           Фиг. 4.7 Операции со стеком                      Page   1-1
 
 
                                         PAGE    ,132
                                         TITLE   Фиг. 4.7 Операции со стеком
            0000                   CODE    SEGMENT
                                         ASSUME  CS:CODE,DS:CODE
            0000                   EXWORD  LABEL   WORD
 
            0000  50                           PUSH    AX        ; Поместить регистр в стек
            0001  56                           PUSH    SI
            0002  0E                           PUSH    CS        ; Можно поместить в стек сегментный регистр
            0003  FF 36 0000 R                 PUSH    EXWORD          ; Можно также поместить в стек ячейку памяти
 
            0007  8F 06 0000 R                 POP     EXWORD          ; Можно извлечь то, что в помещено в стек
            000B  07                           POP     ES        ; Можно извлечь в другое место
            000C  5F                           POP     DI
            000D  5B                           POP     BX
 
            000E  9C                           PUSHF             ; Другая мнемоника для флагов
            000F  9D                           POPF
 
                                   ;-----  Пример, демонстрирующий передачу параметров
 
            0010  50                           PUSH    AX
            0011  53                           PUSH    BX
            0012  51                           PUSH    CX
            0013  52                           PUSH    DX
            0014  E8 0017 R                    CALL    SUBROUTINE      ; Передача управления
                                   ;           ...               ; Продолжение программы
 
            0017                   SUBROUTINE      PROC    NEAR
 
            0017  8B EC                  MOV     BP, SP          ; Занесение в BP адреса стека
            0019  8B 46 02                     MOV     AX, [BP+2]      ; Выборка последнего параметра (DX)
            001C  8B 5E 04                     MOV     BX, [BP+4]      ; Выборка третьего параметра (CX)
            001F  8B 4E 06                     MOV     CX, [BP+6]      ; Выборка второго параметра (BX)
            0022  8B 56 08                     MOV     DX, [BP+8]      ; Выборка первого параметра (AX)
                                   ;           ...
            0025  C2 0008                      RET     8               ; Возврат с уничтожением поля параметров
            0028                   SUBROUTINE      ENDP
            0028                   CODE    ENDS
                                         END
 
                 Фиг. 4.7 Операции со стеком
 
    программе нужно ввести код из порта ввода=вывода 3DAH, а в регистре
    DX находятся важные данные. Следующая последовательность команд
 
      PUSH  DX
      MOV DX,                                         3DAH
      IN  AL,                                         DX
      POP DX
 
      сохраняет регистр DX в стеке на то время, пока он нужен в
    программе для выполнения команды IN.
 
      Операции сохранения регистров в стеке обычно используется в
    начале программы. В большинстве случаев подпрограмма старается
    избегать изменения содержимого любого регистра. Поэтому
    подпрограмма, которой нужны регистры для вычислений и для хранения
    адресов, помещает все необходимые ей регистры в стек до выполнения
    команд обработки. Затем, после выполнения, подпрограмма
    восстанавливает регистры из стека с помощью команд POP.
 
      Помните о том, что стек - это структура типа LIFO. Если в вашей
    программе выполняется последовательность команд
 
      PUSH  BX
      PUSH CX
      POP BX
      POP CX
 
      то результирующим эффектом будет обмен значений в регистрах BX
    и CX. Только тот факт, что в команде PUSH был указан регистр BX, не
    означает, что команда POP, указывающая на тот же регистр,
    восстанавливает первоначальное содержимое регистра BX. Еще одним
    важным моментом является то, что команды PUSH и POP должны быть
    сбалансированы, т.е. каждой команде PUSH должна соответствовать
    команда POP. Точно так же, как и в случае скобок в арифметическом
    выражении, если посылки и извлечения из стека не сбалансированы,
    результаты будут неверны. Более того, несбалансированные команды
    PUSH/POP обычно приводят к возврату из подпрограмм по адресу
    значения данных, а не значения указателя команд из=за того, что
    микропроцессор 8088 записывает в стек адрес возврата. Обычно это
    вынуждает микропроцессор выполнять программу, которую программист
    никогда не писал. Поэтому баланс стековых команд обязателен. Будьте
    особенно внимательны в тех случаях, когда в программе есть условный
    переход вокруг стековых операций; можно легко выпустить из виду
    один из вариантов выполнения, что оставит стек несбалансированным.
 
      Наряду с сохранением данных, программа может использовать стек
    в качестве буфера при некоторых пересылках; в частности, не
    существует команды пересылки, которая бы переносила данные из
    одного сегментного регистра в другой. В обычном случае загрузка
    одного сегментного регистра из другого требует сначала загрузки его
    значения а промежуточный регистр. Это достигается следующей
    последовательностью из двух команд:
 
      MOV   AX,CS   ;переслать значение регистра
                    ;CS в регистр AX
      MOV   DS,AX   ;загрузить это значение в
                    ; регистр DS
 
      Каждая из этих команд имеет длину несколько байт, и эта
    последовательность разрушает содержимое регистра AX. Альтернативным
    подходом может быть
 
      PUSH  CS      ; регистр CS поместить в стек
      POP   DS      ; поместить это значение в регистр DS
 
      Результирующий эффект этой последовательности команд тот же,
    регистр DS загружается из регистра CS. Здесь длина программы -
    всего два байта, и к тому же не требуется промежуточный регистр.
    Однако эти две команды занимают больше времени, так как нужны
    дополнительные циклы чтения и записи в стек. Это - метод потери в
    скорости выполнения ради уменьшения размера объектного кода.




Содержание раздела