Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
      Languages 
      Kernels 
      Packages 
      Books 
      Tests 
      OS 
      Forum 
      Математика 
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Linux Kernel 2.6...2332 
 Trees...1462 
 William Gropp...1420 
 Ethreal 3...1399 
 Ethreal 4...1381 
 C++ Patterns 3...1379 
 Максвелл 3...1367 
 Rodriguez 6...1365 
 Go Web ...1364 
 Robert Love 5...1364 
 Максвелл 5...1363 
 Httpd-> История Ap...1362 
 OS ->Intel Manual 1...1360 
 K&R 1...1359 
 Kamran Husain...1359 
 Ext4 FS...1359 
 Rubni-Corbet -> Глав...1356 
 Perl OOP...1353 
 Erlang...1352 
 Сетунь...1352 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org
Все материалы взяты с сайта OS-FAQ

Inline Assembly

Синтаксис

Ниже показан прототип для вызова asm() из C/C++ :

  asm ( assembler template
       : output operands                   (optional)
       : input operands                    (optional)
       : clobbered registers list          (optional)
       );

Example:

  asm ("addl %1,%0" : "=g"(x) : "g"(y));
   // то же самое , что и :  "x+=y"

Assembler Template

Мы используем синтаксис AT&T. Пример :

    asm( "hlt" ); /* halts the CPU */

Output Operands

Output Operands говорят компилятору , куда положить результат инструкции. Output Operands состоит из 2-х частей,первая часть - строковое обозначение регистра, вторая часть - С-переменная в скобках.

Используемые регистры для output - EAX, EBX,ECX,EDX,ESI,EDI, Знак равенства говорит о том , что это output operand.

    int EAX;
     asm( "movl $0, %%eax" : "=a" (EAX) ); /* pathetic way of EAX = 0; */

Можно явно не указывать регистр и вместо него прописывать r - компилятор сам справится с задачей выбора регистра:

   int current_task;
    asm( "ltr %0" : "=r" (current_task) );

Использование %0, %1 расставляет порядок в использовании операндов.

Вместо такой нумерации можно явно прописывать имя переменной :

    int current_task;
     asm( "ltr %[output]" : [output] "=r" (current_task) );

Такую нотацию можно использовать как для операндов output , так и input .


Input Operands

Input Operands позволяют параметризировать ASM-код; т.е. передавать чисто сишные переменные внутрь АСМ-кода.

   // следующая конструкция бесполезна , ибо мы не знаем значений  EDI, ECX и AL ...
    asm( "cld; rep; stosb" );
 
    // корректно , но несколько сложновато :
    asm( "movl %0, %%edi; movl %1, %%ecx; movb %2, %%al; cld; rep; stosb"
        : : "g"(dest),"g"(amount),"g"(value));
 
    // более компактно
    // Мы пишем в память , адрес которой находится в переменной dest , значение value
    // столько раз , сколько это указано в переменной amount
    asm( "cld; rep; stosb" : : "D" (dest), "c" (amount), "a" (value) );

Подразумевается , что входящие параметры - read-only .


Clobbered Registers List

Важно помнить о следующем : компилятор ничего не знает об Assembler. Если в инлайн-конструкции будет отсутствовать output , компилятор может такую строку интерпретировать как угодно или сделать произвольную оптимизацию . . Этого можно избежать еще одним способом - asm volatile.

Нужно позаботиться также о том , чтобы сохранить значения регистров перед тем , как вы будете делать свой собственный асм-вызов .

Clobbered Registers List - список регистров , разделенных запятыми.

Не нужно сильно утруждаться по поводу выбора регистров - компилятор может сделать это сам . .

"movl $0, %0" : "=g" (x) x может быть чем угодно - компилятор может выбрать регистр , а может и память

Отличия At&t синтаксиса от Nasm


Кстати сказать , AT&T синтаксис является стандартом для большинства не-интеловских платформ . В нем есть инструмент - objdump , который позволяет использовать дебаг.

А теперь несколько существенных отличий AT&T синтаксиса от Intel sytnax, :

  • case sensitive. "MOVL" и "movl" вообще говоря разные вещи :-).
  • numerical base - такая же как и в C: 1 - десятичная система, 01 - 8-ричная, 0x01 - 16-ричная.
  • escapes. Спец-символы - также в стиле C-style (\n, \", \#, \\, ...).
  • comments - 2 варианта - либо C-style ("/* ... */") , либо shell style ("#").
  • directives - вначале идет точка (".align 4" - выравнивание на двойное слово, ".word 0x1234" - то же что и "DW 1234h").
  • strings - определяются с помощью 2-х директив ".ascii" и ".asciz" (с последующим добавлением '\0' конец). Example: msg: .ascii "Hello, World!\n"
  • current location address - обозначается точкой (".", равно Intel syntax "$").
  • initializing memory - .fill (почти то же что и Intel syntax 'times db').
    Пример: .fill 0x1fe - (. - START) , 1, 0 ('1' - размер маски в байтах , START - стартовая метка) , это то же что и Intel syntax times 1FEh - ($-$$) db 0.
  • code counter - может устанавливаться много раз, используяu .org директиву (типа .org 0x1fe + START, где START - стартовая метка.
  • 16/32 bit code генерится с помощью .code16 либо .code32 (равно Intel syntax [BITS 16] и [BITS 32]).
  • target CPU - устанавливается с помощью .arch директивы.
  • label declarations оканчиваются двоеточием
  • new identifier в начале строки должен оканчиваться знаком "равно" и значением , например : FOO = 0xF00
  • end of instruction - новая строка либо точка с запятой
  • line continuation - как и в с строка продолжается с помощью ('\')
  • registers - идут с префиксом процента: %eax, %cs, %esp, etc.
  • source, destination: move, load, store, и другие похожие операции всегда подразумевают наличие 'source, destination'. "movl %eax, %ebx" копирует %eax в %ebx. Может и непривычно - кому как .
  • operand size suffixes - добавляется в виде символа в конце инструкцуии : movb для "move byte", movw для "move word", movl для "move long", etc.
  • direct-address operands не имеют префикса. Так, "movl foo, %eax" копирует "foo" в %eax.
  • immediate operands - имеют префикс доллара ($): "pushl $4" . Доллар добавляется к метке в случае: "movl $foo, %eax" копирует значение метки foo в %eax.
  • indexed / indirect operands - используются в формате segment:displacement (base, index, scale), так: movl %eax, %ss:8(%ebp, 2, 3) (то же что и Intel syntax mov dword [ss:ebp + 2 * 3 + 8], eax, копирует значение %eax по смещению (%ebp + (2 *3) + 8) в сегменте %ss).
  • relative (short addressing) - используется для jump и call инструкций. Для использования (near) -адресации, операнд должен иметь префикс (*).
  • far jumps / calls / returns для этого есть специальные инструкции 'ljmp', 'lcall' и 'lret' .

Macros

Встроенные макросы имеют синтаксис :

.macro <name> <args>
 <operations>
 .endm

Пример:

.macro write string
    movw string, %si
    call printstr
 .endm

Что эквивалентно NASM macro:

%macro write 1
    mov si, %1
    call printstr
 %endmacro

Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье