А.В. Столяров - Программирование на языке ассемблера NASM для ОС Unix (1110582), страница 33
Текст из файла (страница 33)
Âòîðîé ïàðàìåòð ÷èñëî,çàäàþùåå ðåæèì èñïîëüçîâàíèÿ ôàéëà (÷òåíèå, çàïèñü è ïð.); çíà÷åíèåýòîãî ïàðàìåòðà ôîðìèðóåòñÿ êàê áèòîâàÿ ñòðîêà, â êîòîðîé êàæäûéáèò îçíà÷àåò îïðåäåë¼ííóþ îñîáåííîñòü ðåæèìà, íàïðèìåð, äîñòóïíîñòüòîëüêî íà çàïèñü, ðàçðåøåíèå ñîçäàòü íîâûé ôàéë, åñëè åãî íåò, è ò. ï.Ê ñîæàëåíèþ, ðàñïîëîæåíèå ýòèõ áèòîâ ðàçëè÷íî äëÿ ÎÑ Linux è ÎÑFreeBSD; íåêîòîðûå èç ôëàãîâ âìåñòå ñ èõ îïèñàíèÿìè è ÷èñëåííûìèçíà÷åíèÿìè ïðèâåäåíû â òàáëèöå 4.1.
Îòìåòèì, ÷òî íàèáîëåå ÷àñòî âñòðå÷àþòñÿ äâà âàðèàíòà äëÿ ýòîãî ïàðàìåòðà. Ïåðâûé èç íèõ îòêðûòèåôàéëà òîëüêî äëÿ ÷òåíèÿ, â îáåèõ ðàññìàòðèâàåìûõ ñèñòåìàõ ýòîò ñëó÷àé çàäà¼òñÿ ÷èñëîì 0. Âòîðîé ñëó÷àé îòêðûòèå ôàéëà íà çàïèñü,ïðè êîòîðîì ôàéë ñîçäà¼òñÿ, åñëè åãî íå áûëî, à åñëè îí áûë, òî åãîñòàðîå ñîäåðæèìîå òåðÿåòñÿ (â ïðîãðàììàõ íà Ñè ýòî çàäà¼òñÿ êîìáèíàöèåé O_WRONLY|O_CREAT|O_TRUNC).
Äëÿ Linux ñîîòâåòñòâóþùåå ÷èñëîâîåçíà÷åíèå 241h, äëÿ FreeBSD 601h. Òðåòèé ïàðàìåòð âûçîâà open èñïîëüçóåòñÿ òîëüêî â ñëó÷àå ñîçäàíèÿ ôàéëà è çàäà¼ò ïðàâà äîñòóïà äëÿíåãî. Ïîäðîáíîå îïèñàíèå ýòîãî ïàðàìåòðà ìû îïóñêàåì, îòìåòèì òîëüêî, ÷òî â áîëüøèíñòâå ñëó÷àåâ åãî ñëåäóåò çàäàòü ðàâíûì âîñüìåðè÷íîìó÷èñëó 0666q.Äëÿ âûçîâà open îñîáåííî âàæåí àíàëèç åãî âîçâðàùàåìîãî çíà÷åíèÿè ïðîâåðêà, íå ïðîèçîøëà ëè îøèáêà. Âûçîâ open ìîæåò çàâåðøèòüñÿ ñîøèáêîé â ñèëó ìàññû ïðè÷èí, áîëüøèíñòâî èç êîòîðûõ ïðîãðàììèñòíèêàê íå ìîæåò íè ïðåäîòâðàòèòü, íè ïðåäñêàçàòü: íàïðèìåð, êòî-òîìîæåò íåîæèäàííî ñòåðåòü ôàéë, êîòîðûé ìû ñîáèðàëèñü îòêðûòü íà÷òåíèå, èëè çàïðåòèòü íàì äîñòóï ê äèðåêòîðèè, ãäå ìû íàìåðåâàëèñüñîçäàòü íîâûé ôàéë.
Èòàê, ïîñëå âûïîëíåíèÿ âûçîâà open íàì íåîáõî141íàçâàíèåîïèñàíèåO_RDONLYO_WRONLYO_RDWRO_CREATO_EXCLO_TRUNCòîëüêî ÷òåíèåòîëüêî çàïèñü÷òåíèå è çàïèñüðàçðåøèòü ñîçäàíèå ôàéëàïîòðåáîâàòü ñîçäàíèå ôàéëàåñëè ôàéë ñóùåñòâóåò, óíè÷òîæèòüåãî ñîäåðæèìîååñëè ôàéë ñóùåñòâóåò, äîïèñûâàòü âêîíåöO_APPENDçíà÷åíèå äëÿLinux FreeBSD000h000h001h001h002h002h040h200h080h800h200h400h400h008hÒàáëèöà 4.1.
Íåêîòîðûå ôëàãè äëÿ âòîðîãî ïàðàìåòðà âûçîâà openäèìî ïðîâåðèòü, íå ñîäåðæèò ëè ðåãèñòð EAX îòðèöàòåëüíîå çíà÷åíèå (âÎÑ Linux) èëè íå âçâåä¼í ëè ôëàã CF (â ÎÑ FreeBSD). Åñëè âûçîâ çàêîí÷èëñÿ óñïåøíî, òî ðåãèñòð EAX ñîäåðæèò äåñêðèïòîð îòêðûòîãîôàéëà (ïîòîêà ââîäà èëè âûâîäà). Èìåííî ýòîò äåñêðèïòîð òåïåðü ñëåäóåò èñïîëüçîâàòü â êà÷åñòâå ïåðâîãî ïàðàìåòðà â âûçîâàõ read è writeäëÿ ðàáîòû ñ ôàéëîì. Êàê ïðàâèëî, ýòî çíà÷åíèå ñëåäóåò ñðàçó æå ïîñëåâûçîâà ñêîïèðîâàòü â ñïåöèàëüíî îòâåä¼ííóþ äëÿ íåãî îáëàñòü ïàìÿòè.Êîãäà âñå äåéñòâèÿ ñ ôàéëîì çàâåðøåíû, åãî ñëåäóåò çàêðûòü.
Ýòîäåëàåòñÿ ñ ïîìîùüþ âûçîâà close, èìåþùåãî íîìåð 6. Âûçîâ ïðèíèìàåòîäèí ïàðàìåòð, ðàâíûé äåñêðèïòîðó çàêðûâàåìîãî ôàéëà. Ïîñëå ýòîãî ïîòîê ââîäà-âûâîäà ñ òàêèì äåñêðèïòîðîì ïåðåñòà¼ò ñóùåñòâîâàòü;ïîñëåäóþùèå âûçîâû open ìîãóò ñíîâà èñïîëüçîâàòü òîò æå íîìåð äåñêðèïòîðà.Çàäà÷à â ÎÑ Unix ìîæåò óçíàòü ñâîé íîìåð (òàê íàçûâàåìûé èäåíòèôèêàòîð ïðîöåññà) ñ ïîìîùüþ âûçîâà getpid, à òàêæå íîìåð ñâîåãîíåïîñðåäñòâåííîãî ¾ïðåäêà¿ (ïðîöåññà, ñîçäàâøåãî äàííûé ïðîöåññ) ñïîìîùüþ âûçîâà getppid.
Âûçîâ getpid â îáåèõ ðàññìàòðèâàåìûõ ñèñòåìàõ èìååò íîìåð 20, òîãäà êàê âûçîâ getppid èìååò íîìåð 64 â ÎÑLinux è íîìåð 39 â ÎÑ FreeBSD. Îáà âûçîâà íå ïðèíèìàþò ïàðàìåòðîâ;çàïðàøèâàåìûé íîìåð âîçâðàùàåòñÿ â êà÷åñòâå ðåçóëüòàòà ðàáîòû âûçîâà ÷åðåç ðåãèñòð EAX. Îòìåòèì, ÷òî ýòè äâà âûçîâà âñåãäà çàâåðøàþòñÿóñïåøíî, îøèáêàì òóò ïðîñòî íåîòêóäà âçÿòüñÿ.Ñèñòåìíûé âûçîâ kill (íîìåð 37) ïîçâîëÿåò îòïðàâèòü ñèãíàë ïðîöåññó ñ çàäàííûì íîìåðîì. Âûçîâ ïðèíèìàåò äâà ïàðàìåòðà, ïåðâûé çàäà¼ò íîìåð ïðîöåññà7 , âòîðîé çàäà¼ò íîìåð ñèãíàëà; â ÷àñòíîñòè, ñèãíàë 15 (SIGTERM) ïðåäïèñûâàåò ïðîöåññó çàâåðøèòüñÿ (íî ïðîöåññ ìîæåò7 Íà ñàìîì äåëå ìîæíî îòïðàâèòü ñèãíàë ñðàçó ãðóïïå ïðîöåññîâ èëè äàæå âñåìïðîöåññàì â ñèñòåìå, íî ïîäðîáíîå îïèñàíèå ýòîãî âûõîäèò çà ðàìêè íàøåãî êóðñà.142ýòîò ñèãíàë ïåðåõâàòèòü è çàâåðøèòüñÿ íå ñðàçó, ëèáî âîîáùå íå çàâåðøàòüñÿ), à ñèãíàë 9 (SIGKILL) óíè÷òîæàåò ïðîöåññ, ïðè÷¼ì ýòîò ñèãíàëíåëüçÿ íè ïåðåõâàòèòü, íè èãíîðèðîâàòü.ßäðà îïåðàöèîííûõ ñèñòåì ñåìåéñòâà Unix ïîääåðæèâàþò ñîòíè ðàçíîîáðàçíûõ ñèñòåìíûõ âûçîâîâ; çàèíòåðåñîâàííûå ÷èòàòåëè ìîãóò íàéòè èíôîðìàöèþ îá ýòèõ âûçîâàõ â ñåòè Èíòåðíåò èëè â ñïåöèàëüíîéëèòåðàòóðå.
Îòìåòèì, ÷òî äëÿ îçíàêîìëåíèÿ ñ èíôîðìàöèåé î ñèñòåìíûõ âûçîâàõ æåëàòåëüíî çíàòü ÿçûê ïðîãðàììèðîâàíèÿ Ñè, äà è ðàáîòàíà óðîâíå ñèñòåìíûõ âûçîâîâ ñ ïîìîùüþ ÿçûêà Ñè ñòðîèòñÿ ãîðàçäîïðîùå. Áîëåå òîãî, íåêîòîðûå ñèñòåìíûå âûçîâû â îòäåëüíûõ ñèñòåìàõìîãóò íå ïîääåðæèâàòüñÿ ÿäðîì, à âìåñòî ýòîãî ýìóëèðîâàòüñÿ áèáëèîòå÷íûìè ôóíêöèÿìè Ñè, ÷òî äåëàåò èõ èñïîëüçîâàíèå â ïðîãðàììàõ íàÿçûêå àññåìáëåðà ïðàêòè÷åñêè íåâîçìîæíûì.  ýòîé ñâÿçè íåëèøíèìáóäåò íàïîìíèòü, ÷òî ÿçûê àññåìáëåðà ìû ðàññìàòðèâàåì ñ ó÷åáíîé, àíå ïðàêòè÷åñêîé öåëüþ. Ïðîãðàììû, ïðåäíàçíà÷åííûå äëÿ ïðàêòè÷åñêîãî ïðèìåíåíèÿ, ëó÷øå ïèñàòü íà Ñè èëè íà äðóãèõ ïîäõîäÿùèõ ÿçûêàõâûñîêîãî óðîâíÿ. 4.4. Ïàðàìåòðû êîìàíäíîé ñòðîêèÏðè ðàáîòå â îïåðàöèîííîé ñðåäå ÎÑ Unix ìû, êàê ïðàâèëî, çàïóñêàåì ïðîãðàììû, óêàçûâàÿ êðîìå èõ èì¼í åù¼ è îïðåäåë¼ííûå ïàðàìåòðû èìåíà ôàéëîâ, îïöèè è ò.
ï. Òàê, ïðè çàïóñêå àññåìáëåðà NASM ìûìîæåì íàïèñàòü ÷òî-òî âðîäånasm -f elf prog.asmÑëîâà, óêàçàííûå ïîñëå èìåíè ïðîãðàììû, íàçûâàþòñÿ ïàðàìåòðàìèêîìàíäíîé ñòðîêè .  äàííîì ñëó÷àå ýòèõ àðãóìåíòîâ òðè: êëþ÷ ¾-f¿,ñëîâî ¾elf¿, îáîçíà÷àþùåå íóæíûé íàì ôîðìàò ðåçóëüòàòà òðàíñëÿöèè,è èìÿ ôàéëà ¾prog.asm¿. Îòìåòèì, ÷òî è ñàìî èìÿ ïðîãðàììû, â äàííîìñëó÷àå ¾nasm¿, ñ÷èòàåòñÿ ýëåìåíòîì êîìàíäíîé ñòðîêè. Èíà÷å ãîâîðÿ,êîìàíäíàÿ ñòðîêà ïðåäñòàâëÿåò ñîáîé ìàññèâ ñòðîê, ñîñòîÿùèé â äàííîìñëó÷àå èç ÷åòûð¼õ ýëåìåíòîâ: ¾nasm¿, ¾-f¿, ¾elf¿ è ¾prog.asm¿.Åñòåñòâåííî, ìû è ñàìè ìîæåì íàïèñàòü ïðîãðàììó, ïîëó÷àþùóþ òåèëè èíûå ñâåäåíèÿ ÷åðåç êîìàíäíóþ ñòðîêó. Ïðè çàïóñêå ïðîãðàììû îïåðàöèîííàÿ ñèñòåìà îòâîäèò â å¼ àäðåñíîì ïðîñòðàíñòâå ñïåöèàëüíóþ îáëàñòü ïàìÿòè, â êîòîðîé ðàñïîëàãàåò ñòðîêè, ñîñòàâëÿþùèå êîìàíäíóþñòðîêó.
Èíôîðìàöèÿ îá àäðåñàõ ýòèõ ñòðîê âìåñòå ñ èõ îáùèì êîëè÷åñòâîì äëÿ óäîáñòâà ïîìåùàåòñÿ â ñòåê çàïóñêàåìîé çàäà÷è, ïîñëå ÷åãîóïðàâëåíèå ïåðåäà¼òñÿ íàøåé ïðîãðàììå. Òàêèì îáðàçîì, â òîò ìîìåíò,êîãäà íàøà ïðîãðàììà íà÷èíàåò âûïîëíÿòüñÿ ñ ìåòêè _start, íà âåðøèíå ñòåêà (òî åñòü ïî àäðåñó [esp]) ðàñïîëàãàåòñÿ ÷åòûð¼õáàéòíîå öåëîå ÷èñëî, ðàâíîå êîëè÷åñòâó ýëåìåíòîâ êîìàíäíîé ñòðîêè (âêëþ÷àÿ èìÿ143ïðîãðàììû), â ñëåäóþùåé ïîçèöèè ñòåêà (ïî àäðåñó [esp+4]) ðàñïîëàãàåòñÿ àäðåñ â ïàìÿòè, ãäå íàõîäèòñÿ èìÿ, ïî êîòîðîìó íàøó ïðîãðàììóâûçâàëè, äàëåå (ïî àäðåñó [esp+8]) íàõîäèòñÿ àäðåñ ïåðâîãî ïàðàìåòðà,ïîòîì âòîðîãî ïàðàìåòðà è ò.
ä. Êàæäûé ýëåìåíò êîìàíäíîé ñòðîêè õðàíèòñÿ â ïàìÿòè â âèäå ñòðîêè (ìàññèâà ñèìâîëîâ), îãðàíè÷åííîé ñïðàâàíóëåâûì áàéòîì.Äëÿ ïðèìåðà ðàññìîòðèì ïðîãðàììó, ïå÷àòàþùóþ ïàðàìåòðû ñâîåé êîìàíäíîé ñòðîêè (âêëþ÷àÿ íóëåâîé). Ïîëüçîâàòüñÿ ñðåäñòâàìèstud_io.inc ìû óæå íå ñòàíåì, ïîñêîëüêó çíàåì, êàê áåç íèõ îáîéòèñü.Äëÿ èñïîëüçîâàíèÿ âûçîâà write íàì ïîíàäîáèòñÿ çíàòü äëèíó êàæäîé ïå÷àòàåìîé ñòðîêè, ïîýòîìó äëÿ óäîáñòâà ìû îïèøåì ïîäïðîãðàììóstrlen, ïîëó÷àþùóþ â êà÷åñòâå ïàðàìåòðà ÷åðåç ñòåê àäðåñ ñòðîêè è âîçâðàùàþùóþ ÷åðåç ðåãèñòð EAX äëèíó ýòîé ñòðîêè (ïðåäïîëàãàåòñÿ, ÷òîêîíåö ñòðîêè îáîçíà÷åí íóëåâûì áàéòîì).
Êðîìå òîãî, îòäåëüíóþ ïîäïðîãðàììó (newline) îïèøåì äëÿ ïå÷àòè ñèìâîëà ïåðåâîäà ñòðîêè; ïðèýòîì íàì ïîòðåáóåòñÿ îáëàñòü ïàìÿòè èç îäíîãî áàéòà, ðàâíîãî 10, òî åñòüêîäó ïåðåâîäà ñòðîêè, ÷òîáû ïåðåäàâàòü å¼ àäðåñ âûçîâó write, è ìû ýòóîáëàñòü ïàìÿòè îòâåä¼ì ïðÿìî â ñåêöèè .text8 âìåñòå ñ êîäîì ïîäïðîãðàììû newline ñðàçó ïîñëå êîìàíäû ret, ïîìåòèâ ëîêàëüíîé ìåòêîé.Åù¼ îäèí ñâîåîáðàçíûé ìîìåíò ñîñòîèò â òîì, ÷òî íàøà ïðîãðàììà áóäåò ðàñ÷èòàíà êàê äëÿ ðàáîòû ñ ÎÑ Linux, òàê è äëÿ ðàáîòû ñÎÑ FreeBSD.
Ïîñêîëüêó ñèñòåìíûå âûçîâû â ýòèõ ÎÑ âûïîëíÿþòñÿ ïîðàçíîìó, ìû âîñïîëüçóåìñÿ äèðåêòèâàìè óñëîâíîé êîìïèëÿöèè äëÿ âûáîðà òîãî èëè èíîãî òåêñòà. Ýòè äèðåêòèâû áóäóò ïðåäïîëàãàòü, ÷òî ïðèêîìïèëÿöèè ïîä ÎÑ Linux ìû îïðåäåëÿåì (â êîìàíäíîé ñòðîêå NASM)ìàêðîñèìâîë OS_LINUX, à ïðè ðàáîòå ïîä FreeBSD ñèìâîë OS_FREEBSD.Òàêèì îáðàçîì, ïðè ðàáîòå ïîä ÎÑ Linux íàø ïðèìåð (íàçîâ¼ì åãîcmdl.asm) íóæíî áóäåò êîìïèëèðîâàòü ñ ïîìîùüþ êîìàíäûnasm -f elf -dOS_LINUX cmdl.asmà ïðè ðàáîòå ïîä ÎÑ FreeBSD êîìàíäîénasm -f elf -dOS_FREEBSD cmdl.asmÈòàê, ïèøåì òåêñò:section .textglobal _startstrlen:; arg1 == address of the stringpush ebpmov ebp, esp8 Ìû ìîæåì òàê ïîñòóïèòü, ïîñêîëüêó ýòó îáëàñòü ïàìÿòè íàøà ïðîãðàììà íåìåíÿåò; åñëè áû ýòî áûëî íå òàê, ïðèøëîñü áû ðàñïîëàãàòü å¼ â ñåêöèè .data.144push esixor eax, eaxmov esi, [ebp+8]; arg1.lp:cmp byte [esi], 0jz .quitinc esiinc eaxjmp short .lp.quit: pop esipop ebpretnewline:pushad%ifdef OS_FREEBSDpush dword 1push dword .nwlpush dword 1 ; stdoutmov eax, 4 ; writepush eaxint 80hadd esp, 16%elifdef OS_LINUXmov edx, 1mov ecx, .nwlmov ebx, 1mov eax, 4int 80h%else%error please define either OS_FREEBSD or OS_LINUX%endifpopadret.nwldb 10_start:mov ecx, [esp]mov esi, espadd esi, 4again: push dword [esi]call strlenadd esp, 4push esipush ecx%ifdef OS_FREEBSDpush eaxpush dword [esi]145%else%endifpush dword 1 ; stdoutmov eax, 4 ; writepush eaxint 80hadd esp, 16movmovmovmovintedx,ecx,ebx,eax,80heax[esi]14call newlinepop ecxpop esiadd esi, 4loop again%ifdef OS_FREEBSDpush dword 0mov eax, 1 ; _exitpush eaxint 80h%elsemov ebx, 0mov eax, 1int 80h%endif 4.5.
Ïðèìåð: êîïèðîâàíèå ôàéëàÐàññìîòðèì åù¼ îäèí ïðèìåð ïðîãðàììû, àêòèâíî âçàèìîäåéñòâóþùåé ñ îïåðàöèîííîé ñèñòåìîé. Ýòà ïðîãðàììà áóäåò ïîëó÷àòü ÷åðåç ïàðàìåòðû êîìàíäíîé ñòðîêè èìåíà äâóõ ôàéëîâ îðèãèíàëà è êîïèèè ñîçäàâàòü êîïèþ ïîä çàäàííûì èìåíåì ñ çàäàííîãî îðèãèíàëà. Íàøàïðîãðàììà áóäåò ðàáîòàòü äîñòàòî÷íî ïðîñòî: ïðîâåðèâ, ÷òî åé äåéñòâèòåëüíî ïåðåäàíî äâà ïàðàìåòðà, îíà ïîïûòàåòñÿ îòêðûòü ïåðâûé ôàéëíà ÷òåíèå, âòîðîé ôàéë íà çàïèñü è, åñëè åé ýòî óäàëîñü, òî öèêëè÷åñêè ÷èòàòü èç ïåðâîãî ôàéëà äàííûå ïîðöèÿìè ïî 4096 áàéò, ïîêà íåâîçíèêíåò ñèòóàöèÿ ¾êîíåö ôàéëà¿. Ñðàçó ïîñëå ÷òåíèÿ êàæäîé ïîðöèèïðîãðàììà áóäåò çàïèñûâàòü ïðî÷èòàííîå âî âòîðîé ôàéë.