Բոլորը գիտեն, որ C/C++ ֊ի կոդից կարելի է կանչել ասսեմբլերական հրամաններ inline assembler ֊ի միջոցով։ Պարզվում է, որ հակառակ կանչը ոչ միայն հնարավոր է, այլ նաև օգտագործվում է օպերացիոն համակարգի սկզբնական բեռնիչից (bootloader) միջուկի (kernel) կոդի թողարկման համար (քանի որ որպես կանոն օպերացիոն համակարգի բեռնիչը գրված է assembler֊ով, իսկ միջուկը C֊ով)․ ասսեմբլերի կոդից կարելի է կանչել C֊ական ֆունկցիաներ։ Կոդը գրելուց առաջ, պետք է համոզվել, որ բոլոր անհարեշտ գործիքները առկա են մեր օպերացիոն համակարգում։
Ասսեմբլերի կոդից օբյեկտային ֆայլ (*.o) ստանալու համար ես օգտագործում են nasm ասսեմբլերը: Իմ օպերացիոն համակարգը ubuntu ֊ն է, իսկ դրա համար nasm ֊ը տեղադրվում է հետևյալ հրամանով․
sudo apt-get install nasm
Մեզ պետք է նաև gcc կոմպիլյատորը։ linux ֊ում այն լռությամբ տեղակայված չէ և տեղակայման համար պետք գրել հետևյալ հրամանը․
sudo apt-get install build-essential
ՈՒնենք երկու ֆայլ print.asm և main.c։
print.asm
extern c_main section .text global _start _start: call c_main mov eax, 1 xor ebx, ebx int 80h
main.c
#include <stdio.h> int c_main() { char str[] = "print from C"; printf("%s\n", str); return 0; }
Կարծում եմ կոդերը չափազանց պարզև բոլորի համար հասկանալի են։ Թերևս միան պետք է նշել, որ extern c_main հրամանով նշում ենք, որ կանչվող c_main() ֆունկցիան հանդիսանում է արտաքին ֆունկցիա։
Նախ անհրաժեշտ է main.c և print.asm ելայետային կոդի ֆայլերից ստանալ համապատասխան օբյեկտային ֆայլերը՝ main.o և print.o: Թե ինչ է օբյեկտային ֆայլը կարող էք կարդալ այստեղից object file: Եթե կարճ, ապա օբյեկտային ֆայլը դա անմիջապես կոմպիլյատորի ելքն է։ Այն երկուական ֆայլ է, որը պարունակում է մեքենայական կոդ և կատարողական ֆայլից տարբերվում է միայն նրանով, որ link ֊ի փուլը չի անցել (կոպիտ ասած ֆունկցիաների կանչերի հասցեները կապակցված չեն)։
print.asm ֊ից օբյեկտային ֆայլ ստանում ենք հետևյալ հրամանով․
nasm -g -f elf printf.asm -o printf.o
Այստեղ -g ֊ով պահում ենք debug֊ի համար անհրաժեշտ ինֆորմացիան, ֊o ով տալիս ենք օբյեկտային ֆայլի անունը, իսկ -f elf ով էլ ասում ենք, որ ուզում ենք ելքում ստանալ օբյեկտային ֆայլ։
main.c ֊ից օբյեկտային ֆայլ ստանում ենք հետևյալ հրամանով․
gcc -c -o main.o main.c -g
Այստեղ -g և ֊o նույն նշանակությունն ունեն ինչ հաջորդ հրամանում էր, իսկ -c ով նշում ենք, որ ելքում պետք է ստանալ միայն օբյեկտային ֆայլ։
Այժմ այս երկու օբյեկտային ֆայլերը միասին link ենք անում և ստանում ենք կատարողական ֆայլ։
ld -o print print.o main.o -lc -I/lib/ld-linux.so.2
Մեզ մնաց միայն աշխատացնել ստացված print կատարողական ֆայլը, ինչն էլ անում ենք հետևյալ հրամանով․
Comments: no replies