А.В. Столяров - Программирование на языке ассемблера NASM для ОС Unix (1110582), страница 32
Текст из файла (страница 32)
Èíîå äåëî, åñëè ìû ïèøåì íà ÿçûêå àññåìáëåðà. Íèêàêîé áèáëèîòåêè ñèñòåìíûõ âûçîâîâ ó íàñ ïðè ýòîì íåò, íîìåð âûçîâà ìû äîëæíû óêàçàòü â ïðîãðàììåÿâíî, òàê ÷òî â òåêñòå, ïðåäíàçíà÷åííîì äëÿ Linux, ïðèä¼òñÿ èñïîëüçîâàòü ÷èñëî 64, òîãäà êàê äëÿ FreeBSD íóæíî áóäåò ÷èñëî 39. Ïîëó÷àåòñÿ,÷òî íàïèñàííûé íàìè èñõîäíûé òåêñò áóäåò ïðèãîäåí äëÿ îäíîé ñèñòåìû è îøèáî÷åí äëÿ äðóãîé. Àíàëîãè÷íî îáñòîÿò äåëà è ñ íåêîòîðûìè÷èñëîâûìè êîíñòàíòàìè, êîòîðûå âûçîâû ïîëó÷àþò íà âõîä.×àñòè÷íî íàñ ìîæåò âûðó÷èòü ìàêðîïðîöåññîð ñ åãî äèðåêòèâàìèóñëîâíîé êîìïèëÿöèè, ëèáî ìû ìîæåì îãðàíè÷èòüñÿ òîëüêî îäíîé ñèñòåìîé (÷òî, íà ñàìîì äåëå, íå ñîâñåì ïðàâèëüíî). Ê ñ÷àñòüþ, ñèñòåìûFreeBSD è Linux âñ¼ æå âî ìíîãîì ïîõîæè äðóã íà äðóãà è ÷èñëîâûå çíà÷åíèÿ, ñâÿçàííûå ñ ñèñòåìíûìè âûçîâàìè, ÷àñòè÷íî ñîâïàäàþò (ñ äðó5 Åñòåñòâåííî, ÎÑ Linux ðàññìàòðèâàåòñÿ â âàðèàíòå äëÿ i386; âåðñèè ýòîé ñèñòåìû,ïðåäíàçíà÷åííûå äëÿ äðóãèõ àïïàðàòíûõ àðõèòåêòóð, óñòðîåíû èíà÷å.136ãèìè ñèñòåìàìè ñåìåéñòâà Unix áûëî áû õóæå).
Òàê èëè èíà÷å, êòî ïðåäóïðåæä¼í, òîò âîîðóæ¼í. 4.3.1. Êîíâåíöèÿ ÎÑ Linuxßäðî Linux íà ïëàòôîðìå i386 èñïîëüçóåò äëÿ îñóùåñòâëåíèÿ ñèñòåìíîãî âûçîâà ïðåðûâàíèå ñ íîìåðîì 80h. Íîìåð ñèñòåìíîãî âûçîâà ïåðåäà¼òñÿ ÿäðó ÷åðåç ðåãèñòð EAX; åñëè ñèñòåìíûé âûçîâ ïðèíèìàåò ïàðàìåòðû, òî îíè ðàñïîëàãàþòñÿ, ñîîòâåòñòâåííî, â ðåãèñòðàõ EBX, ECX, EDX,ESI è EDI; îòìåòèì, ÷òî âñå ïàðàìåòðû ñèñòåìíûõ âûçîâîâ ÿâëÿþòñÿ ÷åòûð¼õáàéòíûìè çíà÷åíèÿìè ëèáî öåëî÷èñëåííûìè, ëèáî àäðåñíûìè.Ðåçóëüòàò âûïîëíåíèÿ âûçîâà âîçâðàùàåòñÿ ÷åðåç ðåãèñòð EAX, ïðè÷¼ìçíà÷åíèå, çàêëþ÷¼ííîå ìåæäó fffff000h è ffffffffh, ñâèäåòåëüñòâóåò îïðîèñøåäøåé îøèáêå (è ïðåäñòàâëÿåò ñîáîé óñëîâíûé êîä ýòîé îøèáêè).Ðàññìîòðèì äëÿ ïðèìåðà ñèñòåìíûé âûçîâ write, ïîçâîëÿþùèé ïðîèçâåñòè âûâîä äàííûõ ÷åðåç îäèí èç îòêðûòûõ ïîòîêîâ ââîäà-âûâîäà, âòîì ÷èñëå çàïèñü â îòêðûòûé ôàéë, à òàêæå ïå÷àòü íà ñòàíäàðòíûé âûâîä (â ïðîñòîðå÷èè ¾íà ýêðàí¿).
Ýòîò ñèñòåìíûé âûçîâ èìååò íîìåð 4 èïðèíèìàåò òðè ïàðàìåòðà: äåñêðèïòîð (íîìåð) ïîòîêà ââîäà-âûâîäà, àäðåñ ïàìÿòè, ãäå ðàñïîëîæåíû äàííûå, ïîäëåæàùèå âûâîäó, è êîëè÷åñòâîýòèõ äàííûõ â áàéòàõ. Îòìåòèì, ÷òî ïîòîê ñòàíäàðòíîãî âûâîäà â ÎÑUnix èìååò äåñêðèïòîð 1 (òî÷íåå, ïîòîê âûâîäà ïîä íîìåðîì 1 ñ÷èòàåòñÿñòàíäàðòíûì âûâîäîì). Òàêèì îáðàçîì, åñëè ìû õîòèì âûâåñòè ñòðîêó¾íà ýêðàí¿, òî åñòü ñäåëàòü òî, ÷òî äåëàåò ìàêðîñ PRINT, íàì íóæíî áóäåò çàíåñòè ÷èñëî 4 â EAX, çàíåñòè ÷èñëî 1 â EBX, çàíåñòè àäðåñ ñòðîêèâ ECX è äëèíó ñòðîêè â EDX, à çàòåì äàòü êîìàíäó int 80h, ÷òîáûèíèöèèðîâàòü ïðîãðàììíîå ïðåðûâàíèå.Äðóãîé âàæíûé ñèñòåìíûé âûçîâ ýòî âûçîâ _exit, èñïîëüçóåìûéäëÿ çàâåðøåíèÿ ïðîãðàììû.
Îí èìååò íîìåð 1 è ïðèíèìàåò îäèí ïàðàìåòð, ïðåäñòàâëÿþùèé ñîáîé êîä çàâåðøåíèÿ . Ïðîãðàììû èñïîëüçóþòêîä çàâåðøåíèÿ, ÷òîáû ñîîáùèòü îïåðàöèîííîé ñèñòåìå, óñïåøíî ëè îíèñïðàâèëèñü ñ âîçëîæåííîé íà íèõ çàäà÷åé: åñëè âñ¼ ïðîøëî êàê îæèäàëîñü, èñïîëüçóåòñÿ êîä 0, åñëè æå â õîäå ðàáîòû âîçíèêëè òå èëè èíûåîøèáêè, èñïîëüçóþòñÿ êîäû 1, 2 è ò. ä.Çíàÿ âñ¼ ýòî, ìû ìîæåì íàïèñàòü ïðîãðàììó, ïå÷àòàþùóþ ñòðîêó èñðàçó ïîñëå ýòîãî çàâåðøàþùóþñÿ; ôàéë stud_io.inc è åãî ìàêðîñû íàìäëÿ ýòîãî áîëüøå íå íóæíû:global_startsection .datamsgdb "Hello world", 10msg_len equ $-msg137section .text_start: movmovmovmovintmovmovinteax,ebx,ecx,edx,80h41msgmsg_leneax, 1ebx, 080h; âûçîâ write; ñòàíäàðòíûé âûâîä; âûçîâ _exit; êîä "óñïåõ" 4.3.2. Êîíâåíöèÿ ÎÑ FreeBSDÎïèñàíèå êîíâåíöèè ÎÑ FreeBSD íåñêîëüêî ñëîæíåå.
Ýòà ñèñòåìàòàêæå èñïîëüçóåò ïðåðûâàíèå 80h è ïðèíèìàåò íîìåð ñèñòåìíîãî âûçîâà ÷åðåç ðåãèñòð EAX, íî âñå ïàðàìåòðû âûçîâà ïåðåäàþòñÿ íå ÷åðåçðåãèñòðû, à ÷åðåç ñòåê, ïîäîáíî òîìó, êàê ïåðåäàþòñÿ ïàðàìåòðû â ïîäïðîãðàììû â ñîîòâåòñòâèè ñ ñîãëàøåíèÿìè ÿçûêà Ñè, òî åñòü â îáðàòíîìïîðÿäêå (ñì. ñòð. 82).
Êàê è â ÎÑ Linux, âñå ïàðàìåòðû âûçîâîâ ïðåäñòàâëÿþò ñîáîé ÷åòûð¼õáàéòíûå çíà÷åíèÿ. Ðåçóëüòàò âûïîëíåíèÿ ñèñòåìíîãî âûçîâà âîçâðàùàåòñÿ ÷åðåç ðåãèñòð EAX, íî ïðè ýòîì î ïðîèñøåäøåéîøèáêå ñâèäåòåëüñòâóåò íå ïîïàäàíèå çíà÷åíèÿ â ñïåöèàëüíûé ïðîìåæóòîê (êàê ýòî ñäåëàíî â Linux), à óñòàíîâëåííîå çíà÷åíèå ôëàãà CF.
ÅñëèCF ñáðîøåí, òî âûçîâ çàâåðøèëñÿ óñïåøíî è åãî ðåçóëüòàò íàõîäèòñÿ âEAX, åñëè æå ôëàã óñòàíîâëåí, òî ïðîèçîøëà îøèáêà è â EAX çàïèñàí êîäýòîé îøèáêè.Íåîáõîäèìî îòìåòèòü åù¼ îäíó îñîáåííîñòü. ßäðî FreeBSD ïðåäïîëàãàåò, ÷òî óïðàâëåíèå åìó ïåðåäàíî ïóò¼ì îáðàùåíèÿ ê ïðîöåäóðå ñëåäóþùåãî âèäà:kernel:int 80hretÅñëè ó íàñ åñòü òàêàÿ ïðîöåäóðà, íàì äëÿ îáðàùåíèÿ ê ÿäðó äîñòàòî÷íîïîìåñòèòü â ñòåê ïàðàìåòðû òî÷íî òàê æå, êàê äëÿ îáû÷íîé ïðîöåäóðû,çàíåñòè íîìåð âûçîâà â EAX è ñäåëàòü call kernel; ïðè ýòîì êîìàíäàcall çàíåñ¼ò â ñòåê àäðåñ âîçâðàòà, êîòîðûé è áóäåò ëåæàòü íà âåðøèíåñòåêà â ìîìåíò âûïîëíåíèÿ ïðîãðàììíîãî ïðåðûâàíèÿ, à ïàðàìåòðû áóäóò ðàñïîëàãàòüñÿ â ñòåêå íèæå âåðøèíû. ßäðî FreeBSD ó÷èòûâàåò ýòî èíè÷åãî íå äåëàåò ñ ÷èñëîì íà âåðøèíå ñòåêà (âåäü ýòî ÷èñëî àäðåñ âîçâðàòà èç ïðîöåäóðû kernel íèêàêîãî îòíîøåíèÿ ê ïàðàìåòðàì âûçîâàíå èìååò), à íàñòîÿùèå ïàðàìåòðû èçâëåêàåò èç ñòåêà íèæå âåðøèíû (èçïîçèöèé [esp+4], [esp+8] è ò.
ä.)138Ïðè ðàáîòå íà ÿçûêå àññåìáëåðà âûäåëÿòü âûçîâ ïðåðûâàíèÿ â îòäåëüíóþ ïîäïðîãðàììó íå îáÿçàòåëüíî, äîñòàòî÷íî ïåðåä êîìàíäîé intçàíåñòè â ñòåê äîïîëíèòåëüíîå ¾äâîéíîå ñëîâî¿, íàïðèìåð, âûïîëíèâëèøíèé ðàç êîìàíäó push eax (èëè ëþáîé äðóãîé 32-áèòíûé ðåãèñòð).Åñòåñòâåííî, ïîñëå âûïîëíåíèÿ ñèñòåìíîãî âûçîâà è âîçâðàòà èç íåãîíåîáõîäèìî óáðàòü èç ñòåêà âñ¼, ÷òî òóäà áûëî çàíåñåíî; äåëàåòñÿ ýòî,êàê è ïðè âûçîâå îáû÷íûõ ïîäïðîãðàìì, ïóò¼ì óâåëè÷åíèÿ ðåãèñòðà ESPíà íóæíóþ âåëè÷èíó ïðîñòîé êîìàíäîé add.Îïèñûâàÿ â ïðåäûäóùåì ïàðàãðàôå êîíâåíöèþ ÎÑ Linux, ìû äëÿèëëþñòðàöèè èñïîëüçîâàëè âûçîâû write è _exit (ñì. ñòð.
137). Àíàëîãè÷íàÿ ïðîãðàììà äëÿ FreeBSD áóäåò âûãëÿäåòü ñëåäóþùèì îáðàçîì:global_startsection .datamsgdb "Hello world", 10msg_len equ $-msgsection .text_start:pushpushpushmovpushintaddpushmovpushintdword msg_lendword msgdword 1eax, 4eax80hesp, 16dword 0eax, 1eax80h; ñòàíäàðòíûé âûâîä; write; ÷òî óãîäíî; 4 äâîéíûõ ñëîâà; êîä "óñïåõ"; âûçîâ _exit; ÷òî óãîäíîÌû íå ñòàëè î÷èùàòü ñòåê ïîñëå ñèñòåìíîãî âûçîâà _exit, ïîñêîëüêó îíâñ¼ ðàâíî íå âîçâðàùàåò óïðàâëåíèå. ýòîì ïðèìåðå ìû íå îáðàáàòûâàåì îøèáêè, ïðåäïîëàãàÿ, ÷òî çàïèñüâ ñòàíäàðòíûé ïîòîê ââîäà âñåãäà óñïåøíà (ýòî â îáùåì ñëó÷àå íå òàê,íî äîñòàòî÷íî ÷àñòî ïðîãðàììèñòû íà ýòî íå îáðàùàþò âíèìàíèÿ). Åñëèáû ìû õîòåëè îáðàáàòûâàòü îøèáêè ¾÷åñòíî¿, ïåðâîé æå êîìàíäîé ïîñëåint 80h äîëæíà áûëà áû áûòü êîìàíäà jc èëè jnc, äåëàþùàÿ óñëîâíûéïåðåõîä â çàâèñèìîñòè îò ñîñòîÿíèÿ ôëàãà CF, â ïðîòèâíîì ñëó÷àå ìûðèñêóåì, ÷òî î÷åðåäíàÿ êîìàíäà âûñòàâèò ýòîò ôëàã ñîîáðàçíî ñâîèìðåçóëüòàòàì è ïðèçíàê ïðîèñøåäøåé îøèáêè áóäåò ïîòåðÿí.
 ÎÑ Linux ñýòèì áûëî íåñêîëüêî ïðîùå, äîñòàòî÷íî íå òðîãàòü ðåãèñòð EAX, è íè÷åãîíå ïîòåðÿåòñÿ.139 4.3.3. Íåêîòîðûå ñèñòåìíûå âûçîâû Unix âûøåïðèâåä¼ííûõ ïðèìåðàõ ìû ðàññìîòðåëè ñèñòåìíûå âûçîâû_exit è write; íàïîìíèì, ÷òî _exit èìååò6 íîìåð 1 è ïðèíèìàåò îäèíïàðàìåòð êîä çàâåðøåíèÿ, à âûçîâ write èìååò íîìåð 4 è ïðèíèìàåò òðè ïàðàìåòðà, à èìåííî íîìåð äåñêðèïòîðà ïîòîêà âûâîäà (1 äëÿïîòîêà ñòàíäàðòíîãî âûâîäà), àäðåñ îáëàñòè ïàìÿòè, ãäå ðàñïîëîæåíûâûâîäèìûå äàííûå, è êîëè÷åñòâî ýòèõ äàííûõ.Äëÿ ââîäà äàííûõ (êàê èç ôàéëîâ, òàê è èç ñòàíäàðòíîãî ïîòîêà ââîäà, ò.
å. ¾ñ êëàâèàòóðû¿) èñïîëüçóåòñÿ âûçîâ read, èìåþùèé íîìåð 3.Åãî ïàðàìåòðû àíàëîãè÷íû âûçîâó write: ïåðâûé ïàðàìåòð íîìåð äåñêðèïòîðà ïîòîêà ââîäà (äëÿ ñòàíäàðòíîãî ââîäà èñïîëüçóåòñÿ äåñêðèïòîð 0), âòîðîé ïàðàìåòð àäðåñ îáëàñòè ïàìÿòè, â êîòîðîé íåîáõîäèìîðàçìåñòèòü ïðî÷èòàííûå äàííûå, à òðåòèé êîëè÷åñòâî áàéòîâ, êîòîðîå íàäëåæèò ïîïûòàòüñÿ ïðî÷èòàòü. Åñòåñòâåííî, îáëàñòü ïàìÿòè, àäðåñ êîòîðîé ìû ïåðåäà¼ì âòîðûì ïàðàìåòðîì, äîëæíà èìåòü ðàçìåð íåìåíåå ÷èñëà, ïåðåäàâàåìîãî òðåòüèì ïàðàìåòðîì. Î÷åíü âàæíî ïðîàíàëèçèðîâàòü çíà÷åíèå, âîçâðàùàåìîå âûçîâîì read! (íàïîìíèì,÷òî ýòî çíà÷åíèå ñðàçó ïîñëå âûçîâà ñîäåðæèòñÿ â ðåãèñòðå EAX.) Åñëè÷òåíèå ïðîøëî óñïåøíî, âûçîâ âåðí¼ò ñòðîãî ïîëîæèòåëüíîå ÷èñëî êîëè÷åñòâî ïðî÷èòàííûõ áàéòîâ, êîòîðîå, åñòåñòâåííî, íå ìîæåò ïðåâûøàòü ¾çàêàçàííîå¿ ÷åðåç òðåòèé ïàðàìåòð êîëè÷åñòâî, íî âïîëíå ìîæåòîêàçàòüñÿ ìåíüøå (íàïðèìåð, ìû ïîòðåáîâàëè ïðî÷èòàòü 200 áàéòîâ, àðåàëüíî áûëî ïðî÷èòàíî òîëüêî 15). Î÷åíü âàæåí ñëó÷àé, êîãäà readâîçâðàùàåò ÷èñëî 0 ýòî ñâèäåòåëüñòâóåò î òîì, ÷òî â èñïîëüçóåìîìïîòîêå ââîäà âîçíèêëà ñèòóàöèÿ ¾êîíåö ôàéëà¿.
Ïðè ÷òåíèè èç ôàéëîâýòî çíà÷èò, ÷òî âåñü ôàéë ïðî÷èòàí è áîëüøå â í¼ì äàííûõ íåò. Îäíàêî¾êîíåö ôàéëà¿ ìîæåò ïðîèçîéòè íå òîëüêî ïðè ÷òåíèè èç íàñòîÿùåãîôàéëà; òàê, ïðè ââîäå ñ êëàâèàòóðû â ÎÑ Unix ìîæíî ñûìèòèðîâàòüñèòóàöèþ ¾êîíåö ôàéëà¿, íàæàâ êîìáèíàöèþ êëàâèø Ctrl-D.Ïîìíèòå, ÷òî ïðîãðàììà, â êîòîðîé èñïîëüçóåòñÿ âûçîâ readè íå ïðîèçâîäèòñÿ àíàëèç åãî ðåçóëüòàòà, çàâåäîìî íå ìîæåòáûòü ïðàâèëüíîé. Äåéñòâèòåëüíî, ìû â ýòîì ñëó÷àå íå ìîæåì çíàòü,ñêîëüêî ïåðâûõ áàéòîâ íàøåé îáëàñòè ïàìÿòè ñîäåðæàò ðåàëüíî ïðî÷èòàííûå äàííûå, à ñêîëüêî îñòàâøèõñÿ ïðîäîëæàþò ñîäåðæàòü ïðîèçâîëüíûé ¾ìóñîð¿ à çíà÷èò, êàêàÿ-ëèáî îñìûñëåííàÿ ðàáîòà ñ ýòèìèäàííûìè íåâîçìîæíà.Ïðè ÷òåíèè, êàê è ïðè èñïîëüçîâàíèè äðóãèõ ñèñòåìíûõ âûçîâîâ,ìîæåò ïðîèçîéòè îøèáêà.  ÎÑ Linux ýòî ëåãêî îáíàðóæèòü ïî îòðèöàòåëüíîìó çíà÷åíèþ ðåãèñòðà EAX ïîñëå âîçâðàòà èç âûçîâà; â ÎÑ FreeBSDäëÿ óêàçàíèÿ íà òî, ÷òî ïðîèçîøëà îøèáêà, ñèñòåìíûå âûçîâû èñïîëü6 Âî âñÿêîì ñëó÷àå, â ñèñòåìàõ Linux è FreeBSD; â äàëüíåéøåì, åñëè íåò ÿâíûõóêàçàíèé, ïîäðàçóìåâàåòñÿ, ÷òî ñêàçàííîå âåðíî êàê ìèíèìóì äëÿ ýòèõ äâóõ ñèñòåì.140çóþò ôëàã CF (carry ag): åñëè âûçîâ çàâåðøèëñÿ óñïåøíî, íà âûõîäå èçíåãî ýòîò ôëàã áóäåò ñáðîøåí, åñëè æå ïðîèçîøëà îøèáêà, òî ôëàã áóäåòóñòàíîâëåí.
Ýòî êàñàåòñÿ è âûçîâà read, è ðàññìîòðåííîãî ðàíåå âûçîâàwrite (ìû íå îáðàáàòûâàëè îøèáî÷íûå ñèòóàöèè, ÷òîáû íå óñëîæíÿòüíàøè ïðèìåðû, íî ýòî íå çíà÷èò, ÷òî îøèáêè íå ìîãóò ïðîèçîéòè), è âñåõîñòàëüíûõ ñèñòåìíûõ âûçîâîâ.Íà ìîìåíò çàïóñêà ïðîãðàììû äëÿ íå¼, êàê ïðàâèëî, îòêðûòû ïîòîêèââîäà-âûâîäà ñ íîìåðàìè 0 (ñòàíäàðòíûé ââîä), 1 (ñòàíäàðòíûé âûâîä)è 2 (ïîòîê äëÿ âûäà÷è ñîîáùåíèé îá îøèáêàõ), òàê ÷òî ìû ìîæåì ïðèìåíÿòü âûçîâ read ê äåñêðèïòîðó 0, à ê äåñêðèïòîðàì 1 è 2 âûçîâ write.×àñòî, îäíàêî, çàäà÷à òðåáóåò ñîçäàíèÿ èíûõ ïîòîêîâ ââîäà-âûâîäà, íàïðèìåð, äëÿ ÷òåíèÿ è çàïèñè ôàéëîâ íà äèñêå. Ïðåæäå ÷åì ìû ñìîæåìðàáîòàòü ñ ôàéëîì, åãî íåîáõîäèìî îòêðûòü, â ðåçóëüòàòå ÷åãî ó íàñ ïîÿâèòñÿ åù¼ îäèí ïîòîê ââîäà-âûâîäà ñî ñâîèì íîìåðîì (äåñêðèïòîðîì).Äåëàåòñÿ ýòî ñ ïîìîùüþ ñèñòåìíîãî âûçîâà open, èìåþùåãî íîìåð 5.Âûçîâ ïðèíèìàåò òðè ïàðàìåòðà. Ïåðâûé ïàðàìåòð àäðåñ ñòðîêè òåêñòà, çàäàþùåé èìÿ ôàéëà; èìÿ äîëæíî çàêàí÷èâàòüñÿ íóëåâûì áàéòîì,êîòîðûé ñëóæèò â êà÷åñòâå îãðàíè÷èòåëÿ.