Директивы ассемблера

    .global main            // экспортировать символ main
main:
    movl $42, %eax
    .intel_syntax noprefix
    mov eax, 42             // код в синтаксисе Intel
    .att_syntax noprefix
    movl $42, eax           // noprefix — без символа %
                            // перед операндами-регистрами

    .att_syntax prefix
    .set answer, 4 * 10
    movl $answer + 2, %eax

    nop
    .byte 0x90
    .skip 5, 0x90

    call finish

    .word 1, 2, 3  // или .short 1, 2, 3
    .int 4, 5, 6
    .quad 7, 8, 9

Переходы и метки

    .global main
main:
    xor %eax, %eax
    xor %ebx, %ebx
loop:
    inc %eax
    inc %ebx
    jmp loop

Флаги

Большинство арифметических инструкций в результате вычисления результата инструкции устанавливают арифметические флаги слова состояния процесса.

Флаг ZF (zero) устанавливается, если в результате операции был получен нуль.

Флаг SF (sign) устанавливается, если в результате операции было получено отрицательное число.

Флаг CF (carry) устанавливается, если в результате выполнения операции произошел перенос из старшего бита результата. Например, для сложения CF устанавливается если результат сложения двух беззнаковых чисел не может быть представлен 32-битным беззнаковым числом.

Флаг OF (overflow) устанавливается, если в результате выполняния операции произошло переполнение знакового результата. Например, при сложении OF устанавливается, если результат сложения двух знаковых чисел не может быть представлен 32-битным знаковым числом.

Обратите внимание, что и сложение addl, и вычитание subl устанавливают одновременно и флаг CF, и флаг OF. Сложение и вычитание знаковых и беззнаковых чисел выполняется совершенно одинаково, и поэтому используется одна инструкция и для знаковой, и для беззнаковой операции.

    stc  // установить CF
    clc  // сбросить CF
    setc %al  // установить %al в 0 или 1 в зависимости от флага
    // seto, setz, ...

Условные переходы

см. справочник

    jz      label   /* переход, если равно (нуль), ZF == 1 */
    jnz     label   /* переход, если не равно (не нуль), ZF == 0 */
    jc      label   /* переход, если CF == 1 */
    jnc     label   /* переход, если CF == 0 */
    jo      label   /* переход, если OF == 1 */
    jno     label   /* переход, если OF == 0 */
    jg      label   /* переход, если больше для знаковых чисел */
    jge     label   /* переход, если >= для знаковых чисел */
    jl      label   /* переход, если < для знаковых чисел */
    jle     label   /* переход, если <= для знаковых чисел */
    ja      label   /* переход, если > для беззнаковых чисел */
    jae     label   /* переход, если >= (беззнаковый) */
    jb      label   /* переход, если < (беззнаковый) */
    jbe     label   /* переход, если <= (беззнаковый) */

Посчитаем до 20:

main:
    xor %eax, %eax
loop:
    add $3, %eax
    call writei32
    mov %eax, %ecx
    subl $20, %ecx
    jl loop
    // тут чего-то не хватает

    .globl main
    cmp src, dst  // недеструктивная версия sub
    test src, dst // недеструктивная версия and

Длинная арифметика

Сложим 64-разрядные числа в edx:eax и edi:esi:

    add %esi, %eax  // сложили младшие половины
    jnc 1f
    inc %edx        // если был перенос, добавляем 1
1:
    add %edi, %edx  // сложили старшие половины

Чтобы не выписывать такую последовательность инструкций, есть инструкция adc (add with carry), которая прибавляет ко второму операнду не только первый операнд, но и значение флага CF:

    add %esi, %eax
    adc %edi, %edx

Аналог для вычитания — sbb (subtract with borrow).

Условные инструкции

см. справочник

Инструкция cmovz (conditional move if ZF) работает как mov, если ZF выставлен, или как nop, если сброшен. Аналогично с другими условиями.