Строка ограничений, состоящая из символов, указывает компилятору на то, как он должен управлять переменной, которую мы ему предоставляем.
Это значит, что мы указываем компилятору то, как мы интерпретируем смысл этой переменной.
Например:
| Unsigned_32'Asm_Output ("=m", Eax); |
Здесь, использование ограничения m (memory) указывает компилятору, что переменная Eax должна быть переменной которая размещается в памяти.
В результате указания этого ограничения, компилятор никогда не будет использовать регистр процессора для хранения этой переменной.
Рассмотрим еще один пример указания ограничения:
| Unsigned_32'Asm_Output ("=r", Eax); |
Здесь, использование ограничения r (register) указывает компилятору на использование регистровой переменной.
Следовательно, для хранения этой переменной компилятор будет использовать регистр процессора.
Если ограничению предшествует символ равенства ("="), то это указывает компилятору, что переменная будет использоваться для сохранения данных.
В показанном ранее примере, при указании ограничения, использовалось ограничение g (global), что позволяет оптимизатору использовать то, что он сочтет более эффективным.
Следует заметить, что существующее число различных ограничений достаточно обширно.
При этом, для процессоров архитектуры Intel x86 наиболее часто используемыми ограничениями являются:
| = | - | ограничение вывода |
| g | - | глобальная переменная (т.е. может быть чем угодно) |
| m | - | переменная в памяти |
| I | - | константа |
| a | - | использовать регистр eax |
| b | - | использовать регистр ebx |
| c | - | использовать регистр ecx |
| d | - | использовать регистр edx |
| S | - | использовать регистр esi |
| D | - | использовать регистр edi |
| r | - | использовать один из регистров eax, ebx, ecx или edx |
| q | - | использовать один из регистров eax, ebx, ecx, edx, esi или edi |
|
Asm ("pushfl" & LF & HT & -- сохранить регистр флагов в стеке "popl %%eax" & LF & HT & -- загрузить флаги из стека в регистр eax "movl %%eax, %0", -- сохранить значение флагов в переменной Outputs => Unsigned_32'Asm_Output ("=g", Eax)); |
|
Asm ("movl %%eax, %0" & "movl %%ebx, %1" & "movl %%ecx, %2", Outputs => (Unsigned_32'Asm_Output ("=g", Eax"), -- %0 = Eax (Unsigned_32'Asm_Output ("=g", Ebx"), -- %1 = Ebx (Unsigned_32'Asm_Output ("=g", Ecx)); -- %2 = Ecx |
|
Asm ("pushfl" & LF & HT & -- сохранить регистр флагов в стеке "popl %%eax" & LF & HT & -- загрузить флаги из стека в регистр eax "movl %%eax, %0", -- сохранить значение флагов в переменной Outputs => Unsigned_32'Asm_Output ("=g", 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; |
|
#APP pushfl popl %eax #NO_APP movl %eax,-40(%ebp) |
|
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; |