Блок кода, который позволяет использовать инструкции специфических
архитектур.
Блок
Asm block используется для вставки конкретных
инструкций машинного кода в программу для того, чтобы выполнять операции,
которые не могут быть выполнены с помощью функций языка или для того, чтобы
вручную оптимизировать производительность чувствительных участков кода.
Текущий компилятор FreeBASIC производит код только для Intel
80x86-базовых
машин; Однако, в будущем, компилятор может быть портирован на платформу,
которая не поддерживает тот же набор инструкций. Поэтому, блоки
Asm
следует использовать только при необходимости, и альтернатива этому коду на
FreeBASIC должна предоставляться, если это возможно.
Возвращаемое значение функции может быть установлено с помощью ключевого
слова
Function в скобках, как
показано в примере ниже.
Комментарии в блоке
Asm имеют тот же синтаксис, как обычные FreeBASIC
Комментарии - используя FreeBASIC-подобный "
' "
комментарий, не "
; " как обычно на ассемблере.
x86 Спецификация:
Синтаксис
Синтаксис встроенного ассемблера является упрощенной
формой синтаксиса Intel. Синтаксис Intel используется
большинством x86 ассемблеров, таких как MASM, TASM, NASM, YASM и FASM.
В общем, назначение инструкции сначала размещается с последующим
источником. На переменные и функции, определенные программой,
можно ссылаться в блоке
Asm. Ассемблер , который
используется FreeBASIC является
GAS, с
помощью директивы
.intel_syntax noprefix , и блоков
Asm
переданных без изменений, за исключением замены имен локальных
переменных для ссылок на фрейм стека, и удаление комментариев.
Синтаксис инструкции в основном такой же как использует FASM,
одно важное отличие в том, что
GAS
требует настройки размера, которым должны следовать слова "
ptr".
' Предполагая, что "blah" это FB глобальная
или локальная переменная UINTEGER
mov eax, [blah] ' ХОРОШО: Размер
виден из eax
inc [blah] ' ПЛОХО: Размер
не дан
inc dword [blah] ' ПЛОХО: Размер
дан, но до сих пор не принят GAS
inc dword Ptr [blah] ' ХОРОШО: "ptr" здесь
необходим для GAS
Сохранение регистра
Когда открывается блок Asm , регистры ebx, esi,
и edi помещаются в стек; при
закрытии блока, эти регистры извлекаются из стека. Это потому,
что эти регистры обязаны сохранять все или почти все
операционные системы, использующие x86 CPU. Поэтому можно
использовать эти регистры без явного сохранения. Вы не должны
менять esp и ebp, так как они обычно
используются для решения локальных переменных.
Имена регистров
Имена регистров для архитектуры x86 записываются
следующим образом в блоке Asm:
- 4-байтовые целые регистры: eax, ebx, ecx, edx, ebp, esp, edi, esi
- 2-байтовые целые регистры: ax, bx, cx, dx, bp, sp, di, si (Младшие
слова 4-байтовых e- регистров)
- 1-байтовые целые регистры: al, ah, bl, bh, cl, ch, dl, dh (старшие
и младшие байты 2-байтовых -x регистров)
- Регистры с плавающей точкой: st(0), st(1), st(2), st(3), st(4), st(5), st(6), st(7)
- MMX регистры (псевдонимы на регистры с плавающей точкой): mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7
- SSE регистры: xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
Набор инструкций
Смотрите эти внешние ссылки:
Небезопасные инструкции
Обратите внимание, что FreeBASIC компилятор выдает
32-битный код защищенного режима для x86, который, как правило,
проходит в непривилегированным уровне пользователя; Поэтому,
привилегированные и чувствительные инструкции соберутся хорошо,
но, возможно, не будут работать правильно или будут вызвать
выполнение ошибок "Общая ошибка защиты", "Недопустимая
инструкция", или SIGILL. Ниже перечислены привилегированные и
чувствительные инструкции начиная с Intel Pentium 4 и Xeon:
- cli *1
- clts
- hlt
- in *1
- ins *1
- int *1
- into *1
- invd
- invlpg
- lgdt
- lidt
- lldt
- lmsw
- ltr
- mov to/from CRn, DRn, TRn
- out *1
- outs *1
- rdmsr
- rdpmc *2
- rdtsc *2
- sti *1
- str
- wbinvd
- wrmsr
- все SSE2 и выше инструкции *2
*1: чувствительны
к IOPL, отлично в DOS
*2: чувствительны к битам разрешений в CR4, смотрите ниже
Привилегированные инструкции будут работать "правильно" в DOS
управляя на 0 кольце ядрами DPMI, как (не по умолчанию) 0 кольцом версии CWSDPMI, WDOSX
или D3X, тем не менее большинство из них не являются действительно полезными
и может быть опасными при выполнении кода DPMI. RDTSC (читающая счётчик TSC)
было показано, что допускается большинством, или всеми операционными
системами.
Однако полезность RDTSC уменьшилась с появлением многоядерных процессоров и
гибернации. SSE2 и выше инструкции отключены "по умолчанию" после
инициализации CPU, Windows и Linux обычно это делают, в DOS это делает хост
DPMI: HDPMI32 позволят это, CWSDPMI нет. Инструкция INT может использоваться
только в DOS версии, обратите внимание, что она работает немного по-другому
в отличии от реального режима DOS, смотрите также
FaqDOS.
Сегментные регистры (
cs,
ds,
es,
fs,
gs)
не должны быть изменены из блока
Asm, за исключением
некоторых случаев с портом DOS (Обратите внимание, что они не работают так
же, как в реальном режиме DOS, смотрите также
FaqDOS).
Операционные системы или DPMI-хосты отвечают за управление памятью; смысл
сегментов (селекторы) в защищенном режиме очень отличается от адресации
памяти в реальном режиме.
Обратите внимание, что эти "небезопасные" инструкции не гарантируют вызов "видимой"
аварии, даже когда работает с недостаточными привилегиями - OS или DPMI хост
может принять решение о "эмуляции" этого, либо функционально (чтение из
некоторых CRx работает под HDPMI32), или "dummy" (ничего не происходит,
инструкция будет проходить молча, как NOP).
См. также