Представления операндов в GAS


  
 
 
  К оглавлению
 
В GAS операнды используются при выполнение вычислительных операций производимых с помощью инструкций центрального процессора согласно с выбранным режимом адресации и подразделяются на три вида:
- регистровый (регистр),
- непосредственный (константа или явно заданный адрес ячейки памяти),
Синтаксис GAS подразумевает, что инструкция имеет два операнда, даже если они явно не заданы, как например в случае ret или leave. Инструкция оперирует с одним, двумя и тремя аргументами в зависимости от кода операции (opcode), определяющего их состав и порядок использования. Ниже представлен формат записи для инструкции, имеющей не более двух операндов.

 mnemonic [scr][,dst]

Здесь mnemonic является мнемоническим обозначением инструкции. Первый операнд (слева) называется источником (src), а второй операнд (справа) приемником (dst). Так же, в документации по GAS различных авторов часто вместо понятия «операнд» используется синоним – аргумент инструкции.
inums_addition:                   # C-функция int inums_addition ( void )
                                  # 
           pushl   %ebp           # { 
           movl	   %esp, %ebp     #

           movzbl  $1,%edx        # неизбежно приводит к ошибке:
                                  # Error: operand type mismatch for `movzbl'
                                    
           movb    $1,%dl         # /* в регистр EDX кладем первое слагаемое,      
           movzbl  %dl,%edx       #    размерностью 8-мь разрядов c обнулением
                                  #    старших 24-х разрядов.  
           movzwl  $65535,%eax    # неизбежно приводит к ошибке:
                                  # Error: operand type mismatch for `movzwl'
     
           movw    $65535,%ax     #    в регистр EАX кладем второе слагаемое c обнулением
           movzwl  %ax,%eax       #    старших 16-ти разрядов.
                                  #
           addl    %edx,%eax      #    операция сложения двух 32-х разрядных чисел, 
                                  #    с результатом в регистре EАX */     
                                  #    
           leave                  #    return (int)(1+65635); 
           ret			  # } 	    
Размер операнда предопределяется префиксом, информирующего процессор, что нужно переключать размерность операндов в процессе выполнения инструкции. Поэтому, в примере выше, использовалась инструкция целочисленного перемещения беззнаковых целых MOVZBL и MOVZWL для получения предсказуемого результата равным 65636, так как регистры EDX и EАX могут хранить значения, оставшиеся от выполнения предыдущих инструкций. При этом, перефикс 'l' указывает на использование операндов 32-х разрядной размерностью.
Так, если упростить выше представленный пример
movb  $1,%dl        # /* в регистр EDX кладем первое слагаемое, 
                    #    размерностью 8-мь разрядов.
movw  $65535,%ax    #    в регистр EАX кладем второе слагаемое
                    #    размерностью 16-ть разрядов
addl    %edx,%eax   #    операция сложения двух 32-х разрядных операндов, 
                    #    с результатом в регистре EАX */     
Вряд ли нам получится с очень большой вероятностью получить результат равным 65636, так как префикс 'b' переключает выполнение инструкции MOV с 8-ю разрядными операндами, а префикс 'w' с 16-ти разрядными операндами. Поэтому, возможность получения неверного результата будет заключаться в старших 24-х разрядах регистра EDX и 16-ти разрядах в регистре EАX, которые при выполнении инструкции MOV остаются неизменными и могут хранить мусор, оставшийся от предыдущей операции. В то время, как инструкция ADD производит операцию сложения с двумя 32-х разрядными операндами включающие в себя необнуленные разряды, как это делали в предыдущем примере с использованием MOVZBL и MOVZWL.

Aдресация памяти

В GAS, обращение по адресу памяти обеспечивается следующим образом:

смещение-в-сегменте:смещение(база,индекс,масштаб)

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

%es:100(%eax,%ebx,2)

Так же нужно помнить, что смещение и масштаб не могут иметь префикс '$'. Более того, при рассмотрении примеров в NASM синтаксисе их нужно отбрасывать.
 

операнд памяти GAS 	Операнд памяти NASM     Вид адресации     
------------------	-------------------     ---------------------------

100			[100]                   непосредственная адресация            
%es:100			[es:100]                прямая адресация отнсительно сегментного регистра ES
(%eax)			[eax]                   косвенная адресация
(%eax,%ebx)		[eax+ebx]               адресация по базе со сдвигом
-10(%eax)		[eax-10]
%ds:-10(%ebp)		[ds:ebp-10]
(%ecx,%ebx,2)		[ecx+ebx*2]             адресация по базе с маштабированием и индексированием
2(,%ebx,2)		[ebx*2]+2               косвенная адресация с масштабированием 

В основном примеры кода c использованием GAS приводятся для сегментной модели распределения памяти, в то время как практически все современные операционные системы используют страничную модель памяти, которая больше подходит для реализации мультизадачного взаимодействия в такой операционной системе как GNU/Linux.
Большинство современных процессоров имеют блок управления памятью MMU (Memory Management Unit), используемый для отображения виртуальных адресов памяти (Virtual Address) коих видит процессор и физические адреса (Physical Address) как они фактически распределены в микросхеме-памяти, т.е. основной задачей данного блока является ретрансляция адреса. Кроме того, блок MMU устанавливает один из атрибутов доступа к соответсвующей области виртуальной памяти такой как "Чтение-записи" (Read-Write) или "Только чтение" (Read-Only), или полный запрет доступа.
Поэтому наличие блока управления памятью MMU в современных процессорах поставило точку в использование сегментной модели как основную для семейства процессоров Intel. К слову данная модель широко применялась в процессорах Intel таких как 8086, 8088, 80186, 80286 и поддерживается так же для обратной совместимости начиная c процессора i386.
Именно с выходом процессора i386 связано рождение Linux, потому что в нем впервые появился такой блок как MMU, позволяющий ретранслировать виртуальные адреса в физические, а каждому процессу стали доступны страницы размером 4 Кбайт, выделяемые операционной системой.
В конечном счете, на пользовательском уровне программиста не очень заботить какая модель распределения памяти задействована, потому что работа процесса с ней будет происходить внутри выделенных ему операционной системой страниц памяти.
Таким образом, приводимый ранее формат адреса имеет следующий практический смысл:

смещение(база,индекс,масштаб)

  
 К оглавлению


Сайт создан в системе uCoz