Ада-95. Компилятор GNAT



         

Ограничения - часть 3


Asm ("pushfl" & LF & HT & -- сохранить регистр флагов в стеке "popl %%eax" & LF & HT & -- загрузить флаги из стека в регистр eax "movl %%eax, %0", -- сохранить значение флагов в переменной Outputs => Unsigned_32'Asm_Output ("=g", Eax));

Фактически, мы можем использовать регистровое ограничение для указания компилятору на необходимость сохранять содержимое регистра eax в переменной Eax

путем написания следующих инструкций встроенного ассемблера:

with Interfaces; use Interfaces; with Ada.Text_IO; use Ada.Text_IO; with System.Machine_Code; use System.Machine_Code; with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;

procedure Flags is

Eax : Unsigned_32; begin

Asm ("pushfl" & LF & HT & -- сохранить регистр флагов в стеке "popl %%eax", -- загрузить флаги из стека в регистр eax Outputs => Unsigned_32'Asm_Output ("=a", Eax)); Put_Line ("Flags register:" & Eax'Img); end Flags;

Примечательно, что ограничение a, указывает компилятору, что переменная Eax будет располагаться в регистре eax.

Генерируемый компилятором, код ассемблера будет иметь следующий вид:

#APP pushfl popl %eax #NO_APP movl %eax,-40(%ebp)

Очевидно, что значение eax сохранено в Eax компилятором после выполнения кода ассемблера.

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

Следует согласиться с тем, что такое удивление справедливо.

Это было необходимо как стартовая точка дискуссии посвященной ограничениям, но, в действительности, в этом нет необходимости.

Таким образом, мы можем переписать исходный текст следующим образом:

with Interfaces; use Interfaces; with Ada.Text_IO; use Ada.Text_IO; with System.Machine_Code; use System.Machine_Code; with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;

procedure Okflags is

Eax : Unsigned_32; begin

Asm ("pushfl" & LF & HT & -- сохранить регистр флагов в стеке "pop %0", -- загрузить флаги из стека в переменную Eax Outputs => Unsigned_32'Asm_Output ("=g", Eax)); Put_Line ("Flags register:" & Eax'Img); end Okflags;

В результате, мы получим результат, который был показан ранее.




Содержание  Назад  Вперед