GCC Inline Assembly — вбудований асемблер компілятора GCC, що являє собою мову макроопису інтерфейсу компільованого високорівневого коду з .
Особливості
Синтаксис і семантика GCC Inline Assembly має наступні суттєві особливості:
- GCC ніяк не інтерпретує вміст асемблерної вставки.
- Використовується явний опис інтерфейсу з асемблерною вставкою.
- Дає компілятору можливість свободи вибору регістрів.
- Дозволяє явно вказати на наявні побічні дії асемблерного коду.
- Дозволяє використовувати всі інструкції (й директиви також), котрі розпізнає асемблер, а не тільки ті, що знає й застосовує gcc.
Попередні відомості
Щоб добре розуміти, як працює GCC Inline Assembly, варто спершу добре уявляти процес компіляції, як він відбувається.
Спочатку gcc викликає препроцесор cpp, який включає заголовочні файли, розгортає всі умовні директиви й здійснєю макропідстановки. Поглянути, що вийшло після макропідстановки, можна командою gcc -E -o preprocessed.c some_file.c
. Ключ -E рідко використовується, переважно при відлагодженні макросів.
Потім gcc аналізує отриманий код, на цій же фазі здійснює оптимізацію коду і в підсумку створює асемблерний код. Подивитися згенерований асемблерний код можна командою gcc -S -o some_file.S some_file.c
.
Далі gcc викликає асемблер gas для того, щоб він створив з асемблерного кода об'єктний код. Зазвичай ключ -c (compile only) використовується в проектах, що складаються з багатьох файлів.
Далі gcc викликає ld для збирання виконуваного файла з отриманих об'єктних файлів.
Для ілюстрації даного процесу створімо файл test.c наступного змісту:
int main() { asm ("Bla-Bla-Bla"); // вставмо таку інструкцію return 0; }
Якщо при компіляції видається попередження -Wimplicit-function-declaration "Неявна декларація функції asm", використовуйте:
__asm ("Bla-Bla-Bla");
Якщо ми скажемо виконати gcc -S -o test.S test.c
, то ми виявимо важливий факт: компілятор обробив «неправильну» інструкцію і результуючий асемблерний файл test.S містить наш рядок «Bla-Bla-Bla». Однак, якщо ми спробуємо створити об'єктний код чи зібрати бінарний файл, то gcc виведе наступне:
test.c: Assembler messages: test.c:3: Error: no such instruction: 'Bla-Bla-Bla'
Повідомлення надходить саме від Асемблера.
Звідси випливає важливий висновок: GCC ніяк не інтерпретує вміст асемблерної вставки, сприймаючи її як макропідстановку часу компіляції.
Синтаксис
Загальна структура
Загальна структура асемблерної вставки має наступний вигляд:
asm [volatile] ("команди і директиви асемблера" : вихідні параметри : вхідні параметри : змінювані параметри);
Втім, існує і більш коротка форма:
asm [volatile] ("команди і директиви асемблера");
Синтаксис команд
Особливістю асемблера gas і компілятора gcc є той факт, що вони використовують незвичний для x86 , котрий суттєво відрізняється від синтаксису Intel. Основні відмінності:
- Порядок операндів:
Операція Джерело,Приймач
. - Назви регістрів мають явний префікс
%
, який вказує, що це регістр. Це дозволяє працювати з змінними, котрі мають ту ж назву, що і якийсь регістр, що неможливо в Intel-синтаксисі, в якому префікси для регістрів не використовуються, а їх назви є зарезервованими ключовими словами. - Явне задання розмірів операндів у суфіксах команд: b-byte, w-word, l-long, q-quadword. В командах типа movl %edx,%eax це може здатися надмірним, однак є доволі наглядним засобом, коли йдеться про incl (%esi) чи xorw $0x7,mask
- Назви констант починаються з $ і можуть бути виразом. Наприклад,
movl $1,%eax
- Значення без префікса означає адресу. Наприклад:
movl $123,%eax
— записати в %eax число 123,movl 123,%eax
— записати в %eax вміст комірки пам'яті з адресою 123,movl var,%eax
— записати в %eax значення змінної var,movl $var,%eax
— завантажити адресу змінної var - Для непрямої адресації необхідно використовувати круглі дужки. Наприклад
movl (%ebx),%eax
— завантажити в %eax значення змінної, за адресою, що міститься в регістрі %ebx - SIB-адресація: зміщення(база, індекс, множник)
Зазвичай ігнорований факт того, що всередині директиви asm можуть міститися не просто асемблерні команди, але й узагалі будь-які директиви, розпізнавані gas, може стати в пригоді. Наприклад, можна вставити вміст бінарного файла в результуючий об'єктний код:
asm( "our_data_file:\n\t" ".incbin \"some_bin_file.txt\"\n\t" // використовуємо директиву .incbin "our_data_file_len:\n\t" ".long .-our_data_file\n\t" // вставляємо значення .long з обчисленою довжиною файла );
І потім адресуватися до цього бінарного файлу:
extern char our_data_file[]; extern long our_data_file_len;
Як працює макропідстановка
Розглянемо, як відбувається підстановка.
Конструкція:
asm ("movl %0,%%eax"::"i"(1));
Перетвориться на
movl $1,%eax
Вхідні і вихідні параметри
Модифікатори
Тонкі моменти
Ключове слово volatile
Ключове слово volatile служить для того, щоб вказати компілятору, що вбудовуваний асемблерний код може давати побічні ефекти, тому спроби оптимізації можуть призвести до логічних помилок.
Випадки, коли ключове слово volatile ставити обов'язково:
Припустімо, всередині циклу є асемблерна вставка, що здійснює перевірку на занятість глобальної змінної і очікування в її звільнення. Коли компілятор починає оптимізувати цикл, він викидиває з циклу все, що явним чином в циклі не змінюється. Оскільки в цьому випадку оптимизуючий компілятор не бачить явної залежності між параметрами асемблерної вставки та змінними, що змінюються в циклі, асемблерна вставка може бути викинута з циклу з усіма випливаючими наслідками.
ПОРАДА: Завжди вказуйте asm volatile в тих випадках, коли ваша асемблерна вставка має «стояти там де стоїть». Особливо це стосується тих випадків, коли ви працюєте з атомарними примітивами.
«memory» в clobber list
Наступний «тонкий момент» — явна вказівка «memory» в clobber list. Окрім простої вказівки компілятору, що асемблерна вставка змінює вміст пам'яті, вона ще служить директивою для компілятора. Це означає, що ті операції звертання в пам'ять, що стоят вище по коду, в результуючому машинному коді будуть виконуватися до тих, що стоять нижче асемблерної вставки. В випадку багатопоточного середовища, коли від цього напряму залежить ризик виникнення , ця обставина є суттєвою.
ПОРАДА № 1:
Швидкий спосіб зробити Memory Barier
#define mbarrier() asm volatile ("":::"memory")
ПОРАДА № 2: Вказування «memory» в clobber list — не лише «хороший тон», але й, у випадку роботи з атомарними операціями, покликаними розрулити race condition, є обов'язковим.
Приклади використання
int main() { int sum = 0, x = 1, y = 2; asm ( "add %1, %0" : "=r" (sum) : "r" (x), "0" (y) ); // sum = x + y; printf("sum = %d, x = %d, y = %d", sum, x, y); // sum = 3, x = 1, y = 2 return 0; }
- код: додати %1 до %0 і зберегти результат в %0
- вихідні параметри: універсальний регістр, збережений в локальну змінну, після виконання асемблерного кода.
- вхідні параметри: універсальні регістри, ініціалізовані від локальних змінних x та y перед виконанням асемблерного коду.
- змінювані параметри: нічого, крім регістрів вводу-виводу.
Примітки
- Викиучебник: Ассемблер в Linux для программистов C. Архів оригіналу за 26 квітня 2022. Процитовано 6 травня 2022.
Посилання
- Офіційна документація [ 23 вересня 2016 у Wayback Machine.]
На цю статтю не посилаються інші статті Вікіпедії. Будь ласка розставте посилання відповідно до . |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
GCC Inline Assembly vbudovanij asembler kompilyatora GCC sho yavlyaye soboyu movu makroopisu interfejsu kompilovanogo visokorivnevogo kodu z OsoblivostiSintaksis i semantika GCC Inline Assembly maye nastupni suttyevi osoblivosti GCC niyak ne interpretuye vmist asemblernoyi vstavki Vikoristovuyetsya yavnij opis interfejsu z asemblernoyu vstavkoyu Daye kompilyatoru mozhlivist svobodi viboru registriv Dozvolyaye yavno vkazati na nayavni pobichni diyi asemblernogo kodu Dozvolyaye vikoristovuvati vsi instrukciyi j direktivi takozh kotri rozpiznaye asembler a ne tilki ti sho znaye j zastosovuye gcc Poperedni vidomostiShob dobre rozumiti yak pracyuye GCC Inline Assembly varto spershu dobre uyavlyati proces kompilyaciyi yak vin vidbuvayetsya Spochatku gcc viklikaye preprocesor cpp yakij vklyuchaye zagolovochni fajli rozgortaye vsi umovni direktivi j zdijsnyeyu makropidstanovki Poglyanuti sho vijshlo pislya makropidstanovki mozhna komandoyu gcc E o preprocessed c some file c Klyuch E ridko vikoristovuyetsya perevazhno pri vidlagodzhenni makrosiv Potim gcc analizuye otrimanij kod na cij zhe fazi zdijsnyuye optimizaciyu kodu i v pidsumku stvoryuye asemblernij kod Podivitisya zgenerovanij asemblernij kod mozhna komandoyu gcc S o some file S some file c Dali gcc viklikaye asembler gas dlya togo shob vin stvoriv z asemblernogo koda ob yektnij kod Zazvichaj klyuch c compile only vikoristovuyetsya v proektah sho skladayutsya z bagatoh fajliv Dali gcc viklikaye ld dlya zbirannya vikonuvanogo fajla z otrimanih ob yektnih fajliv Dlya ilyustraciyi danogo procesu stvorimo fajl test c nastupnogo zmistu int main asm Bla Bla Bla vstavmo taku instrukciyu return 0 Yaksho pri kompilyaciyi vidayetsya poperedzhennya Wimplicit function declaration Neyavna deklaraciya funkciyi asm vikoristovujte asm Bla Bla Bla Yaksho mi skazhemo vikonati gcc S o test S test c to mi viyavimo vazhlivij fakt kompilyator obrobiv nepravilnu instrukciyu i rezultuyuchij asemblernij fajl test S mistit nash ryadok Bla Bla Bla Odnak yaksho mi sprobuyemo stvoriti ob yektnij kod chi zibrati binarnij fajl to gcc vivede nastupne test c Assembler messages test c 3 Error no such instruction Bla Bla Bla Povidomlennya nadhodit same vid Asemblera Zvidsi viplivaye vazhlivij visnovok GCC niyak ne interpretuye vmist asemblernoyi vstavki sprijmayuchi yiyi yak makropidstanovku chasu kompilyaciyi SintaksisZagalna struktura Zagalna struktura asemblernoyi vstavki maye nastupnij viglyad asm volatile komandi i direktivi asemblera vihidni parametri vhidni parametri zminyuvani parametri Vtim isnuye i bilsh korotka forma asm volatile komandi i direktivi asemblera Sintaksis komand Osoblivistyu asemblera gas i kompilyatora gcc ye toj fakt sho voni vikoristovuyut nezvichnij dlya x86 sintaksis AT amp T kotrij suttyevo vidriznyayetsya vid sintaksisu Intel Osnovni vidminnosti Poryadok operandiv Operaciya Dzherelo Prijmach Nazvi registriv mayut yavnij prefiks yakij vkazuye sho ce registr Ce dozvolyaye pracyuvati z zminnimi kotri mayut tu zh nazvu sho i yakijs registr sho nemozhlivo v Intel sintaksisi v yakomu prefiksi dlya registriv ne vikoristovuyutsya a yih nazvi ye zarezervovanimi klyuchovimi slovami Yavne zadannya rozmiriv operandiv u sufiksah komand b byte w word l long q quadword V komandah tipa movl edx eax ce mozhe zdatisya nadmirnim odnak ye dovoli naglyadnim zasobom koli jdetsya pro incl esi chi xorw 0x7 mask Nazvi konstant pochinayutsya z i mozhut buti virazom Napriklad movl 1 eax Znachennya bez prefiksa oznachaye adresu Napriklad movl 123 eax zapisati v eax chislo 123 movl 123 eax zapisati v eax vmist komirki pam yati z adresoyu 123 movl var eax zapisati v eax znachennya zminnoyi var movl var eax zavantazhiti adresu zminnoyi var Dlya nepryamoyi adresaciyi neobhidno vikoristovuvati krugli duzhki Napriklad movl ebx eax zavantazhiti v eax znachennya zminnoyi za adresoyu sho mistitsya v registri ebx SIB adresaciya zmishennya baza indeks mnozhnik Zazvichaj ignorovanij fakt togo sho vseredini direktivi asm mozhut mistitisya ne prosto asemblerni komandi ale j uzagali bud yaki direktivi rozpiznavani gas mozhe stati v prigodi Napriklad mozhna vstaviti vmist binarnogo fajla v rezultuyuchij ob yektnij kod asm our data file n t incbin some bin file txt n t vikoristovuyemo direktivu incbin our data file len n t long our data file n t vstavlyayemo znachennya long z obchislenoyu dovzhinoyu fajla I potim adresuvatisya do cogo binarnogo fajlu extern char our data file extern long our data file len Yak pracyuye makropidstanovka Rozglyanemo yak vidbuvayetsya pidstanovka Konstrukciya asm movl 0 eax i 1 Peretvoritsya na movl 1 eax Vhidni i vihidni parametri ModifikatoriTonki momentiKlyuchove slovo volatile Klyuchove slovo volatile sluzhit dlya togo shob vkazati kompilyatoru sho vbudovuvanij asemblernij kod mozhe davati pobichni efekti tomu sprobi optimizaciyi mozhut prizvesti do logichnih pomilok Vipadki koli klyuchove slovo volatile staviti obov yazkovo Pripustimo vseredini ciklu ye asemblerna vstavka sho zdijsnyuye perevirku na zanyatist globalnoyi zminnoyi i ochikuvannya v yiyi zvilnennya Koli kompilyator pochinaye optimizuvati cikl vin vikidivaye z ciklu vse sho yavnim chinom v cikli ne zminyuyetsya Oskilki v comu vipadku optimizuyuchij kompilyator ne bachit yavnoyi zalezhnosti mizh parametrami asemblernoyi vstavki ta zminnimi sho zminyuyutsya v cikli asemblerna vstavka mozhe buti vikinuta z ciklu z usima viplivayuchimi naslidkami PORADA Zavzhdi vkazujte asm volatile v tih vipadkah koli vasha asemblerna vstavka maye stoyati tam de stoyit Osoblivo ce stosuyetsya tih vipadkiv koli vi pracyuyete z atomarnimi primitivami memory v clobber list Nastupnij tonkij moment yavna vkazivka memory v clobber list Okrim prostoyi vkazivki kompilyatoru sho asemblerna vstavka zminyuye vmist pam yati vona she sluzhit direktivoyu dlya kompilyatora Ce oznachaye sho ti operaciyi zvertannya v pam yat sho stoyat vishe po kodu v rezultuyuchomu mashinnomu kodi budut vikonuvatisya do tih sho stoyat nizhche asemblernoyi vstavki V vipadku bagatopotochnogo seredovisha koli vid cogo napryamu zalezhit rizik viniknennya cya obstavina ye suttyevoyu PORADA 1 Shvidkij sposib zrobiti Memory Barier define mbarrier asm volatile memory PORADA 2 Vkazuvannya memory v clobber list ne lishe horoshij ton ale j u vipadku roboti z atomarnimi operaciyami poklikanimi rozruliti race condition ye obov yazkovim Prikladi vikoristannyaint main int sum 0 x 1 y 2 asm add 1 0 r sum r x 0 y sum x y printf sum d x d y d sum x y sum 3 x 1 y 2 return 0 kod dodati 1 do 0 i zberegti rezultat v 0 vihidni parametri universalnij registr zberezhenij v lokalnu zminnu pislya vikonannya asemblernogo koda vhidni parametri universalni registri inicializovani vid lokalnih zminnih x ta y pered vikonannyam asemblernogo kodu zminyuvani parametri nichogo krim registriv vvodu vivodu PrimitkiVikiuchebnik Assembler v Linux dlya programmistov C Arhiv originalu za 26 kvitnya 2022 Procitovano 6 travnya 2022 PosilannyaOficijna dokumentaciya 23 veresnya 2016 u Wayback Machine Na cyu stattyu ne posilayutsya inshi statti Vikipediyi Bud laska rozstavte posilannya vidpovidno do prijnyatih rekomendacij