Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
NEWS
Последние статьи :
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
  SQL 30.07   
  JFS 10.06   
  B-trees 01.06   
 
TOP 20
 Go Web ...604 
 Trees...344 
 Ethreal 4...279 
 Python...256 
 2.0-> Linux IP Networking...252 
 Secure Programming for Li...245 
 Steve Pate 3...242 
 Mike Perry...223 
 Rubni-Corbet -> Глав...212 
 TCP 3...211 
 Stewens -> IPC 7...202 
 Rubni-Corbet -> Глав...201 
 TCP 2...197 
 Rodriguez 6...194 
 Rubni-Corbet -> Глав...193 
 Stevens-> Глава 25...189 
 C++ Templates 4...186 
 Стивенс 9...181 
 William Gropp...180 
 Rubni-Corbet -> Глав...180 
 
  01.11.2017 : 2330974 посещений 

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

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

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

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