Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ВМСиС.docx
Скачиваний:
25
Добавлен:
22.04.2019
Размер:
278.98 Кб
Скачать

29.Процессор х86: вызов процедуры и прерывания (рамка стека функции в с).

Инструкция вызова функции или процедуры имеет мнемокод call и получает в качестве операнда адрес функции. Адрес функции, также как и адрес перехода в инструкции jmp может задаваться непосредственно через имя функции или же через регистр или же прямо или косвенно через ячейку памяти. При выполнении инструкции call, в отличие от инструкции jmp, помимо загрузки программного счетчика новым значением осуществляется аппаратное выталкивание в стек адреса инструкции, следующей непосредственно за call, т.е. той инструкции, которая будет выполнять после завершения функции. Последней инструкцией функции всегда является инструкция выхода из функции ret, которая снимает с верхушки стека хранящийся там адрес возврата и помещает его в программный счетчик. Инструкция ret имеет две формы: безоперандную и однооперандную. Однооперандная инструкция ret использует только непосредственное представление и прибавляет полученный операнд к указателю на верхушку стека, очищая тем самым стек от параметров функции. Передача параметров функции осуществляется как правило через стек. Поэтому перед вызовом функции программа должна при помощи инструкции push вытолкнуть в стек передаваемые ей параметры.

Существует 2 соглашения по вызовам функций: Pascal и C.

Если используется соглашение по вызовам Pascal, то параметры выталкиваются в стек слева направо, от первого к последнему, а функция завершается инструкцией ret с одним операндом. Величина этого параметра равна количеству байт в стеке, отводимых под параметры.

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

Соглашение по вызовам С создает код чуть большего размера и выполняется чуть дольше, но позволяет использовать функции с переменным количеством параметров.

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

virtual void virtf(int i, float x, float y){. . .;}

. . .

push y

push x

push i

. . .

// поиск адреса функции по ее сигнатуре

lea ebx, virtf

. . .

call ebx

add esp, 12

. . .

30.Процессор х86: инструкции условного перехода.

Инструкции условного перехода имеют мнемокод jX, где X задает условие, при выполнении которого, происходит переход на метку, если условие не выполняется, то переход не осуществляется и выполняется инструкция, следующая непосредственно за инструкцией условного перехода. В инструкциях условного перехода используются только короткие метки.

Условие – это состояние регистра флагов. Поэтому инструкции условного перехода, как правило, следуют непосредственно за инструкциями, при выполнении которых состояние регистра флагов изменяется. Проверяться может состояние как одного флага, так и нескольких. Если требуется проверить один флаг, то его буква помещается в мнемокод инструкции условного перехода. Кроме того, перед буквой флага может стоять префикс n, обозначающий обратное условие, т.е. инструкция jF проверяет установлен ли флаг F, а инструкция jnF – сброшен ли флаг F.

Инструкция

Выполнение

Инструкция

Выполнение

jc

Переход, если установлен флаг переноса

jnc

Переход, если сброшен флаг переноса

jz

Переход, если установлен флаг нуля

jnz

Переход, если сброшен флаг нуля

je

Переход, если установлен флаг нуля

jne

Переход, если сброшен флаг нуля

Jo

Переход, если установлен флаг переполнения

jno

Переход, если сброшен флаг переполнения

Js

Переход, если установлен флаг знака

jns

Переход, если сброшен флаг знака

В реальных программах очень часто встречаются инструкции условного перехода по результатам сравнения чисел. Например, if(a>b) then c:=12 else c:=0; . На ассемблере сравнение целых чисел осуществляется путем их вычитания с последующей проверкой флагов z,c и s. Причем выполнению условия > для знаковых и беззнаковых операндов будут соответствовать различные комбинации флагов c и s. Это же относится и к условиям < , >= , <= . Поэтому в набор команд процессора х86 внесли специальные инструкции условного перехода по результатам сравнения знаковых и беззнаковых чисел, проверяющие за один прием состояние нескольких флагов. В мнемокодах этих инструкций используются следующие буквы:

Буквы

Операнды

Значение

e

Знаковые и беззнаковые

= =

g

Знаковые

>

l

Знаковые

<

ge

Знаковые

>=

le

Знаковые

<=

a

Беззнаковые

>

b

Беззнаковые

<

ae

Беззнаковые

>=

be

Беззнаковые

<=

Кроме того, перед буквами условий, также как и перед буквами флагов, может стоять префикс n. В результате получается следующий набор инструкций, причем почти каждой машинной инструкции будет соответствовать 2 варианта мнемонического обозначения.

Вариант1

Вариант 2

je

-

-

jne

jg

jnle

gl

jnge

jge

jnl

jle

jng

ja

jnbe

jb

jnae

jae

jnb

jbe

jna

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

Таким образом, фрагмент кода - if(a>b) then c:=12 else c:=0; - будет соответствовать следующему коду на ассемблере для знаковых и беззнаковых операндов:

int a,b,c;

. . .

mov eax, a

cmp eax, b

jg m1

mov ecx, 0

jmp m2

m1:mov ecx, 12

m2:mov c, ecx

unsigned int a,b,c;

. . .

mov eax, a

cmp eax, b

ja m1

mov ecx, 0

jmp m2

m1:mov ecx, 12

m2:mov c, ecx

В инструкциях условного перехода используются только короткие метки.