Синтаксис AT&T учить большого смысла не вижу, ведь в as и в g++ появилась опция "режим интел". g++ -masm=intel превосходно генерит асм под ключём -S, именно интел, в общем осталось научится делать асмовые вставки в нём... Просто asm("команда без аргументов"); работает на ура. Но задачка - выполнить примерно следующее: Код (Text): double fpu_cos( double arg ) { double res; asm("fld QWORD PTR arg"); asm("fcos"); asm("fstp QWORD PTR res" ); return res; }; И вот тут as ругается "undefined reference to arg"... А это не радует... В стиле AT&T было как-то мощно через двоеточия отсылки к внешним переменным из асма, а как это делается в режиме intel?
Не рулед. Там нет ответов на вопрос который я задал. Ни одного вообще примерно похожего. Про то что g++ и as уже позволяют юзать intel синтаксис я сам написал в первом же посте. Проблема вообще в другом. Как во встроенный асм передать адреса сишных переменных в этом синтаксисе (intel). Методом святого гугла ничего путнего найти не могу. Либо речь идет об AT&T синтаксисе, либо команды в intel-синтаксисе встроенного асма не имеют аргументов-операндов из C-шной части проги. Скрещивая знания, почёрпнутые из ссылок про AT&T пытаюсь приладить по подобной схеме аргументы-С-переменные к intel-синтаксису и вроде даже начало получаться, но к сожалению бздрищ и ах.... Туплю последние два часа, пытаясь загрузить в eax адрес аргумента arg (G++/AS): Код (Text): double fpu_cos( double arg ) { double res = 0; asm("mov eax, QWORD PTR %[asm_arg]" : : [asm_arg] "m" (arg)); ... } error: ambigious operand size invalid for mov. При этом вариантов уже испробовал кучу чертову, и без QWORD PTR и вместо "m" - "X" и т.п. и т.д, всего уже не упомню. Смысл - чтобы в eax оказался адрес arg, чтобы скормить его потом fld QWORD PTR [eax], но увы, не компилица.... Ругается на всякое. P.S. Напоминаю, что всё это компилится с ключем -masm=intel и действительно в моей версии опознаваться должно правильно. Одиночная asm("fcos"); не вызывает никаких ошибок, что для AT&T синтаксиса неприемлемо.
первая ссылка в гугле Код (Text): #include <stdio.h> double fpu_sqrt( double arg ) { double res; asm("fld %0"::"m"(arg)); asm("fsqrt"); asm("fstp %0":"=m"(res) ); return res; }; int main() { printf("%f\n", fpu_sqrt(3)); return 0; }
Voodoo Спасибо за код, он действительно скомпилировался без ошибок, хотя я готов был поклястся, когда увидел, что такой вариант уже пробовал. Трабла правда в том, что я действительно пробовал этот вариант и отказался, т.к. он генерирует ужасную хрень: думает что если "m", то это не на стеке должно быть, а.... опять же копирует в стек ниже адресом, чтобы передать уже асму как параметр. Вот оно: Код (Text): _Z8fpu_sqrtd: .LFB534: push ebp .LCFI2: mov ebp, esp .LCFI3: sub esp, 24 .LCFI4: mov eax, DWORD PTR [ebp+8] mov DWORD PTR [ebp-24], eax mov eax, DWORD PTR [ebp+12] mov DWORD PTR [ebp-20], eax #APP # 55 "main.cpp" 1 fld QWORD PTR [ebp-24] # 0 "" 2 # 56 "main.cpp" 1 fcos # 0 "" 2 # 57 "main.cpp" 1 fstp QWORD PTR [ebp-8] # 0 "" 2 #NO_APP fld QWORD PTR [ebp-8] leave ret Обратите внимание, на то что происходит в метке .LCFI4 - всё ради того, чтобы асм-код ниже инструкцией "схавал" ту самую "m" (операнд из памяти). Абсолютно непонятно зачем и почему. Такое ощущение, что "m" входит в режим "read-only" или что-то из такого дурдома. Поэтому я действительно этого (для чтения) достигал, но как увидел результат - отказался сразу же. И на каких-то других (вроде "f") спецификаторах достигал нужного - fld QWORD PTR [ebp+8] и ликовал, но применить то же по отношению к fstp никак не мог! =((( Та же проблема и у записи - вместо того чтобы сразу писать в res, со всеми вытекающими, сперва в переменную пишет, потом снова достаёт, чтобы вернуть из функции, как-будто бы не видит что запись шла в эту же переменную изначально, как будто бы всё-таки, упущены другие важные квалификаторы, делающие код эффективным по AT-энд-T-шному.... Блин... В MVSC++ асм оптимизировался без всяких таких костылей, как влитой инструмент в язык. Тут же видно, что всё сложнее, инструмента в языке встроенного нет, но есть все причиндалы, чтобы он вёл себя с ними как можно эффективнее, но пока не получается. =(
Помогите перевести inline intel в inline at&t формат Код (Text): func (UINT64 x) { { _asm { mov eax, dword ptr x[0] test eax, eax jz f_hi bsf eax, eax jmp f_ret f_hi: bsf eax, dword ptr x[4] add eax, 20h f_ret: } } } Особенно интересует - как записать mov eax, dword ptr x[0] и bsf eax, dword ptr x[4] (и разве допустима запись x[0] и x[4] ?). intel2gas спотыкается на данной адресации
угу реальный гемор, этот встроеннный асм, хоть at&t, хоть intel btw 2 Voodoo пример компилится, но работает неверно, так что низачот завтра прийдётся медитировать на мануал, так как эмипирические наблюдения ничего полезного за полдня не дали
вот такое работает в качестве fsqrt, инструмент мощный, этот inline gcc asm, но разобраться очень тяжело, и похоже intel режим только костылей добавляет, а помощи от него никакой, передать параметры функции как в этом примере - ну никак, а ld ругается на неизвестные символьные имена... Код (Text): #include <stdio.h> double fpu_sqrt(double x) { double res; asm ("fsqrt" : "=t" (res): "0" (x)); return res; }; int main() { printf("%f\n",fpu_sqrt(3)); return 0; }
black_hole Я могу поверить, что за intel синтаксис можно держаться, если писать на асме много. Но если речь идёт об inline вставке -- то какая разница? Не машинный код, мнемониками -- уже хорошо, и ладно. info gcc "C Implementation" Constraints Там всё расписано. В секции же "Extended Asm" описано как этим пользоваться. Ну и, в конце концов, если этого мало можно сказать: Код (Text): find /usr/src/linux -name \*.c | xargs grep asm | grep -v include И поизучать это дело на примерах.