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

       

Параметры вывода


При желании сохранить содержиме регистра eax в какой-либо переменной, первым желанием будет написать что-нибудь подобное следующему:

procedure Getflags is

Eax : Unsigned_32; begin

Asm ("pushfl" & LF & HT & -- сохранить регистр флагов в стеке "popl %%eax" & LF & HT & -- загрузить флаги из стека в регистр eax "movl %%eax, Eax") -- сохранить значение флагов в переменной Put_Line ("Flags register:" & Eax'Img); end Getflags;

с попыткой сразу сохранить содержимое регистра процессора eax в переменной Eax.

Увы, также просто как это может выглядеть, это не будет работать, поскольку нельзя точно сказать чем будет являться переменная Eax.

Несколько подумав, можно сказать: Eax - это локальная переменная, которая, в обычной ситуации, будет размещена в стеке.

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

Таким образом, возникает законный вопрос: как необходимо специфицировать переменную, чтобы обеспечить корректную работу для обоих случаев?

Ответ на этот вопрос заключается в том, чтобы не сохранять результат в переменной Eax

самостоятельно, а предоставить компилятору возможность самостоятельно выбирать правильный операнд для использования.

Для этой цели применяется понятие параметра вывода.

Программа, использующая инструкцию вывода, будет выглядеть так как она была написана ранее:

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

Следует обратить внимание на то, что мы заменили обращение к переменной Eax

на обращение к операнду %0.

Однако, компилятору необходимо указать, чем является %0:

Outputs => Unsigned_32'Asm_Output ("=g", Eax));

Здесь, часть "Outputs =>" укажет, что это именованный параметр инструкции ассемблера (полный синтаксис инструкций ассемблера будет рассмотрен позже в "Синтаксис GNAT").

Напомним также, что ранее мы описали переменную Eax, как переменную типа Interfaces.Unsigned_32.

Мы описали ее таким образом, поскольку 32-битный беззнаковый целый тип удачнее всего подходит для представления регистра процессора.

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

Unsigned_32'Asm_Output ("=g", Eax);

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

Type'Asm_Output (строка_ограничений, имя_переменной)

Смысл имени переменной и атрибута 'Asm_Output достаточно понятны.

Остается понять, что означает и для чего используется строка_ограничений.



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