× К оглавлению На главную Об авторе

   Дата и время публикации:
Дата и время модификации:

Помещает данные в стек.


СИНТАКСИС
        push reg
АРГУМЕНТЫ

reg — регистры общего назначения или константа.

ОПИСАНИЕ

В настоящее время, широкоприменяемой архитектуры х86-64, данная инструкция используется для помещения на вершину или дно стека значений, хранящихся в регистрах общего назначения RAX, RBX, RCX, RDX, RSP, RBP, RSI, RDI или констант, предворяемых символом '$'. В основном, она используется во время выполнения вызова функции (подпрограммы) в целях сохранения (стеке) слепка используемых её регистров и/или указателей кадра стека регистров (%rsp) и (%rbp) вызывающей функции. А так же передачи аргументов вызываемой функции через стек от вызывающей, если их количество больше шести.

Примечание.
Таблица назначение регистров x86-64
Регистр Назначение Сохранение значений на всех вызовах функций
%rax регистeр-аккумулятор, возврат значения, временное хранения Нет
%rbx хранение данных вызывающих функций Да
%rc Используется для передачи 4-го аругмента функции Нет
%rdx Используется для передачи 3-го аругмента функции Нет
%rsp Указатель программного стека (положение вершины) Да
%rbp хранение данных вызывающих функций; указатель базы Да
%rsi Используется для передачи 2-го аругмента функции Нет
%rdi Используется для передачи 1-го аругмента функции Нет
%r8 Используется для передачи 5-го аругмента функции Нет
%r9 Используется для передачи 6-го аругмента функции Нет
%r10-r11 регистры временного хранения Нет
%r12-r15 регистры хранение данных вызывающих функций Да

Ранее, в архитектуре x86-32 разрядность регистров стека ebp и esp устанавливалась согласно конфигурации, принятой по-умолчанию и равной 32 разряда, поэтому push в исходном коде ассемблера писали 'pushl'.

B архитектуре x86-64 инструкция push уже манипулирует с 64-х разрядным стеком, поэтому push в исходном коде ассемблера следует писать как 'pushq'. В тоже время, 32-х и 16-ти разрадные явные операции со стеком в данной архитектуре запрещены, как показано в листинге 1

Листинг 1

 

           ... 
           pushl %eax# неправильные инструкция
           pushw %ax
           pushq %rax# Правильная инструкция: копирует значение в стека по текущему
                     # положению с одновременным его уменьшнием в регистре %rsp 
           pushq %r10# Сохранение данных регистeров вызывающих функций
           pushq %r11
           ... 

Причиной запрета 32-х и 16-ти разрадных операций со стеком, можно предположить, является уменьшение на 8 байт (согласно рамерности данных в x86-64) указателя текущего положения стека регистра%rsp. Поэтому для разрешения такого рода операций нужно сообщать о переходе к режиму i386-16 с использованием директив ' .code16 ' или ' .code32 '.

i386-16 При использовании в GCC экспериментальной 16-ти разрядной поддержки (только для x86 архитектуре) наряду с указанием в коде ассемблера директив .code16 или .code16gcc, устанавливаемой обычно опцией компилятора --code16gcc, следует писать как 'pushw'. При этом, если используется ' .code16gcc ' нужно помнить, что в отличии от ' .code16 ' 'pusha' и 'pushf' имеют размерность 32 разряда. По-мимо 16-ти разрядной поддержки сужествует возможностьпереключения к 32-х разрядной с использованием ' .code32 ', а к 64-х разрядной – c директивой ' .code64 '. В тоже время нужно помнить, что директива ' .code16gcc ' обеспечивает экспериментальную поддержку 16-ти разрядного кода компилятором GCC и отличается от ' .code16 ' в том, что инструкции ' call ', ' ret ', ' enter ', ' leave ', ' push ', ' pop ', ' pusha ', ' popa ', ' pushf ', and ' popf ' приводятся по умолчанию к 32-м разрядам. Так как манипуляция указателем стека производится одним и тем же способом во время вызова функции, доступ к её параметрам осуществляется с тем же самым смещением как в 32-х разрядном режиме. Таким образом, вынужден ' .code16gcc ' автоматически добовлять также префиксы размерности, где необходимо использовать 32-х адресный режим, который генерирует GCC. А так же не забывать, что код генерируемый в 16-ти разрядном режиме не будет работать на 16-ти разрядном режиме предпроцессора 80386. Для написания кода для подобных процессоров, нужно отказаться от использования каких-либо 32-х разрядных конструкций, которые требуются как для вывода адреса, так и префикс размерности операнда.
 
     .code16gcc
.
.
.
     pushw %bx# сохранение регистра BX	 
.
.
.

Взамен инструкции push обычно пользуются парой инструкций sub и mov, как это показано ниже в листинге 2

Листинг 2

 
 
     #pushq %rax
     subl $8,%rsp    # увеличение стека на 8 адресов вниз	 
     movq %rax,(%rsp)# сохранение значение RAX в вершине стека 

Библиография

См. п.п.32-35 общей библиографии