Основу программы составляют инструкции, которые и определяют поведение программы, ее действия. Наиболее распространенной инструкцией в ассемблере является инструкция копирования данных или инструкции mov. В зависимости от разрядности копируемых данных она имеет ряд вариаций:
movq: копирует 64-битное число
movl: копирует 32-битное число
movw: копирует 16-битное число
movb: копирует 8-битное число, то есть 1 байт
То есть к названию инструкции прибавляется суффикс, который указывает на тип данных: q, l, w и b. Эти инструкции принимают два операнда. Первый параметр представляет, что копируем или откуда копируем или источник данных, а второй параметр - куда копируем:
movq source, destination
В качестве источника данных может выступать число - непосредственный операнд, регистр или адрес в памяти. В качестве второго операнда - регистр или адрес в памяти.
Если мы копируем число, то перед числом ставится символ $. А при указании регистра перед его именем ставится символ %. Например:
.globl _start .text _start: movq $60, %rax movq $22, %rdi syscall
В данном случае помещаем в регистр RAX число 60 - номер системного вызова Linux закрытия программы. А в регистр RDI помещается число 22 - произвольный код статуса выполнения программы. Пример работы программы:
eugene@Eugene:~# cd asm eugene@Eugene:~/asm# as hello.s -o hello.o eugene@Eugene:~/asm# ld hello.o -o hello eugene@Eugene:~/asm# ./hello eugene@Eugene:~/asm# echo $? 22 eugene@Eugene:~/asm#
В обоих случаях числа помещаются в 64-разрядный регистр - RAX или RDI, поэтому для помешения числа в регистр применяется инструкция movq, которая предназначены для 64-разрядных значений. Если операнды представляют 32-разрядные значения, то применяется инструкция movl:
.globl _start .text _start: movl $60, %eax # EAX = 60 movl $5, %edi # EDI = 5 syscall
Здесь числа помещаются в 32-разрядные регистры EAX и EDI, поэтому для копирования числа применяется инструкция movl. То же самое касается других инструкций копирования - movw (для 16-разрядных чисел) и movb (для 8-разрядных чисел)
Аналогично в качестве источника данных можно использовать регистр:
.globl _start .text _start: movq $60, %rax # RAX = 60 movq $11, %rcx # RCX = 11 movq %rcx, %rdi # RDI = RCX syscall
Вторая инструкция здесь помещает число 11 в регистр RCX, а затем значение из RCX копирует в регистр RDI. То есть в итоге в RDI будет храниться число 11.
Перед числом в ассемблере GAS указывается символ доллара $, например, $22
. Этот символ указывает, что последуещее число рассматривается именно как число,
а не как метка/адрес в памяти.
Ассемблер позволяет определять числа в различных системах. Это делается с помощью специальных префиксов. В общем случае, когда перед числом нет никакого префикса, число использует десятичную систему:
movq $11, %rdi
Здесь в регистр RDI помещается десятичное число 11.
Если надо определить число в двоичном формате, то перед числом указывается префикс 0b:
movq $0b1011, %rdi
Здесь бинарное число 10112
, которое в десятичной системе представляет число 1110
, помещается в RDI.
Если надо определить число в шестнадцатеричном формате, то перед числом указывается префикс 0x:
movq $0xb, %rdi
Здесь шестнадцатеричное число b16
, которое в десятичной системе также представляет число 1110
, помещается в RDI.