А.В. Столяров - Программирование на языке ассемблера NASM для ОС Unix (1110582), страница 21
Текст из файла (страница 21)
Ïðè÷èíîé òîìó, âî-ïåðâûõ, îòñóòñòâèå â Ïàñêàëå àðèôìåòèêè óêàçàòåëåé, è âî-âòîðûõ,ïðèíèöïèàëüíî äðóãîé ïîäõîä ê ðàáîòå ñî ñòðîêàìè, êîòîðûé â äàííîé êîíêðåòíîé çàäà÷å ìåíåå óäîáåí (õîòÿ âî ìíîãèõ äðóãèõ çàäà÷àõ îêàçûâàåòñÿ óäîáíåå,÷åì ïîäõîä, òðàäèöèîííûé äëÿ Ñè). Âîò ïðèìåð ðåàëèçàöèè:function match(str, pat: string): boolean;function do_match(str_ind, pat_ind: integer): boolean;var i: integer;beginwhile true do beginif pat_ind > length(pat) then begindo_match := str_ind > length(str); exitend;if pat[pat_ind] = '*' then beginfor i:=0 to length(str)-str_ind+1 doif do_match(str_ind+i, pat_ind+1) then begindo_match := true; exitend;86do_match := false; exitend elseif (str_ind > length(str)) or((str[str_ind] <> pat[pat_ind]) and(pat[pat_ind] <> '?'))then begindo_match := false; exitend;str_ind := str_ind + 1;pat_ind := pat_ind + 1;endend;beginmatch := do_match(1,1)end;Ïåðåäàâ â ôóíêöèþ match ñòðîêè, ïîäëåæàùèå ñîïîñòàâëåíèþ, ìû äàëüøå ìåíÿåì òîëüêî èíäåêñû; ÷òîáû îðãàíèçîâàòü ïî íèì ðåêóðñèþ, ìû îïèñàëè ëîêàëüíóþôóíêöèþ do_match, êîòîðàÿ è âûïîëíÿåò âñþ ðàáîòó.Ðåàëèçàöèþ íà ÿçûêå àññåìáëåðà ìû âûïîëíèì â âèäå ïîäïðîãðàììû, êîòîðóþ íàçîâ¼ì match.
Ïîäïðîãðàììà áóäåò ïðåäïîëàãàòü, ÷òîåé ïåðåäàíî äâà ïàðàìåòðà àäðåñ ñòðîêè ([ebp+8]) è àäðåñ îáðàçöà ([ebp+12]); ñàìà ïîäïðîãðàììà áóäåò èñïîëüçîâàòü îäíó ÷åòûð¼õáàéòíóþ ïåðåìåííóþ äëÿ õðàíåíèÿ I; ïîä íå¼ áóäåò âûäåëÿòüñÿ ìåñòîâ ñòåêîâîì ôðåéìå è îíà áóäåò, ñîîòâåòñòâåííî, ðàñïîëàãàòüñÿ ïî àäðåñó[ebp-4]. Äëÿ óâåëè÷åíèÿ ñêîðîñòè ðàáîòû íàøà ïîäïðîãðàììà â ñàìîìíà÷àëå ñêîïèðóåò àäðåñà èç ïàðàìåòðîâ â ðåãèñòðû ESI (àäðåñ ñòðîêè) èEDI (àäðåñ îáðàçöà). Êðîìå òîãî, äëÿ âûïîëíåíèÿ àðèôìåòè÷åñêèõ äåéñòâèé íàøà ïîäïðîãðàììà áóäåò èñïîëüçîâàòü ðåãèñòð EAX. ×åðåç íåãîæå ïîäïðîãðàììà áóäåò âîçâðàùàòü ðåçóëüòàò ñâîåé ðàáîòû: ÷èñëî 0 êàêîáîçíà÷åíèå ëîãè÷åñêîé ëæè (ñîîòâåòñòâèå íå íàéäåíî) èëè ÷èñëî 1 êàêîáîçíà÷åíèå ëîãè÷åñêîé èñòèíû (ñîîòâåòñòâèå íàéäåíî).¾Îòáðàñûâàíèå¿ ñèìâîëîâ èç íà÷àëà ñòðîê ìû áóäåì ïðîèçâîäèòüïðîñòûì óâåëè÷åíèåì ðàññìàòðèâàåìîãî àäðåñà ñòðîêè: äåéñòâèòåëüíî,åñëè ïî àäðåñó string íàõîäèòñÿ ñòðîêà, ìû ìîæåì ñ÷èòàòü, ÷òî ïî àäðåñó string+1 íàõîäèòñÿ òà æå ñòðîêà, êðîìå ïåðâîé áóêâû.Íåîáõîäèìî îáðàòèòü âíèìàíèå, ÷òî ïîäïðîãðàììà áóäåò ðåêóðñèâíîâûçûâàòü ñàìà ñåáÿ, è, áóäó÷è âûçâàííîé ðåêóðñèâíî, äîëæíà áóäåò âûïîëíÿòü ðàáîòó íàä çíà÷åíèÿìè, îòëè÷àþùèìèñÿ îò òåõ, ÷òî áûëè çàäàíû â ïðåäûäóùåì âûçîâå.
Ìåæäó òåì, ðåãèñòðû â êà÷åñòâå õðàíèëèùàëîêàëüíûõ äàííûõ ïîíàäîáÿòñÿ êàê èñõîäíîìó âûçîâó ïîäïðîãðàììû,òàê è ¾âëîæåííîìó¿ (ðåêóðñèâíîìó), íî â ïðîöåññîðå òîëüêî îäèí íàáîððåãèñòðîâ. Ìû âûéäåì èç ïîëîæåíèÿ âïîëíå òðàäèöèîííûì ñïîñîáîì:íàøà ôóíêöèÿ áóäåò ïåðåä íà÷àëîì ðàáîòû ñîõðàíÿòü â ñòåêå íå òîëüêîEBP, íî è âñå îñòàëüíûå ðåãèñòðû, êîòîðûå îíà èñïîëüçóåò, à ïåðåä âîç87âðàòîì óïðàâëåíèÿ ðåãèñòðû áóäóò âîññòàíàâëèâàòüñÿ; â äàííîì ñëó÷àåìû èñïîëüçóåì ESI, EDI è EAX, íî EAX â ëþáîì ñëó÷àå ¾èñïîðòèòñÿ¿, ïîñêîëüêó ÷åðåç íåãî ìû âîçâðàùàåì èòîãîâîå çíà÷åíèå, òàê ÷òî ñîõðàíÿòüíóæíî òîëüêî ESI è EDI. Òàê îáû÷íî äåéñòâóþò íå òîëüêî â ñëó÷àå ðåêóðñèè, íî è âîîáùå â ëþáûõ ïîäïðîãðàììàõ: ýòîò ïîäõîä ïîçâîëÿåò âëþáîé èç íàøèõ ïîäïðîãðàìì íå äóìàòü î òîì, ÷òî ïîäïðîãðàììû, ê êîòîðûì ìû îáðàùàåìñÿ, ìîãóò èñïîðòèòü ðåãèñòðû, ãäå õðàíÿòñÿ íóæíûåíàì çíà÷åíèÿ.match:push ebpmov ebp, espsub esp, 4; ÍÀ×ÀËÎ ÏÎÄÏÐÎÃÐÀÌÌÛ; îðãàíèçóåì ñòåêîâûé ôðåéì;;push esi;push edi;mov esi, [ebp+8];mov edi, [ebp+12];.again:;;;cmp byte [edi], 0;jne .not_end;cmp byte [esi], 0;jne near .false;jmp .true;.not_end:;cmp byte [edi], '*';jne .not_star;;mov dword [ebp-4], 0 ;.star_loop:;mov eax, edi;inc eax;push eaxmov eax, esi;add eax, [ebp-4];push eax;call match;;add esp, 8;test eax, eax;jnz .true;;;;ëîêàëüíàÿ ïåðåìåííàÿ Iáóäåò ïî àäðåñó [ebp-4]ñîõðàíÿåì ðåãèñòðû ESI è EDI(EAX âñ¼ ðàâíî èçìåíèòñÿ)çàãðóæàåì ïàðàìåòðû: àäðåñàñòðîêè è îáðàçöàñþäà ìû âåðí¼ìñÿ, êîãäàñîïîñòàâèì î÷åðåäíîéñèìâîë è ñäâèíåìñÿîáðàçåö êîí÷èëñÿ?åñëè íåò, ïðûãàåìîáðàçåö êîí÷èëñÿ, à ñòðîêà?åñëè íåò, òî âåðíóòü ËÎÆÜêîí÷èëèñü îäíîâðåìåííî: ÈÑÒÈÍÀåñëè îáðàçåö íå êîí÷èëñÿ...íå çâ¼çäî÷êà ëè â åãî íà÷àëå?åñëè íåò, ïðûãàåì îòñþäàçâ¼çäî÷êà! îðãàíèçóåì öèêëI := 0ãîòîâèìñÿ ê ðåêóðñ.
âûçîâóñíà÷àëà âòîðîé àðãóìåíò:îáðàçåö ñî ñëåä. ñèìâîëàòåïåðü ïåðâûé àðãóìåíò:ñòðîêà ñ I-ãî ñèìâîëà(íàïîìíèì, [ebp-4] - ýòî I)âûçûâàåì ñàìè ñåáÿ, íîñ íîâûìè ïàðàìåòðàìèïîñëå âûçîâà î÷èùàåì ñòåê÷òî íàì âåðíóëè?Âåðíóëè íå íîëü, ò.å. ÈÑÒÈÍÓÇíà÷èò, îñòàòîê ñòðîêèñîïîñòàâèëñÿ ñ îñòàòêîìîáðàçöà => âåðí¼ì èñòèíó88add eax, [ebp-4];;;;cmp byte [esi+eax], 0 ;;je .false;inc dword [ebp-4];jmp .star_loop;.not_star:mov al, [edi]cmp al, '?'je .questcmp al, [esi]jne .falsejmp .goon.quest:cmp byte [esi], 0jz .false.goon: inc esiinc edijmp .again.true:mov eax, 1jmp .quit.false:xor eax, eax.quit:pop edipop esimov esp, ebppop ebpretâåðíóëè 0, ò.å. ËÎÆÜíàäî ïîïðîáîâàòü áîëüøåñèìâîëîâ "ñïèñàòü" íàýòó çâ¼çäî÷êóÍî, áûòü ìîæåò, ñòðîêàóæå êîí÷èëàñü?Òîãäà ïðîáîâàòü áîëüøå íå÷åãîÈíà÷å ïðîáóåì: I := I + 1è â íà÷àëî öèêëà ïî I;;;;;;;;;;;;;;;;;;;;;ñþäà ìû ïîïàäàåì, åñëè îáð.íå ïóñò è íå íà÷.
ñ '*'ìîæåò áûòü, òàì çíàê '?'åñëè äà, ïðûãàåì îòñþäàåñëè íåò, ñèìâîëû â íà÷àëåñòðîêè è îáðàçöà äîëæíûñîâïàäàòü; åñëè ñòðîêàêîí÷èëàñü, ýòà ïðîâåðêàòîæå íå ïðîéä¼òÍå ñîâïàëè (èëè êîí. ñòðîêè)=> âîçâðàùàåì ËÎÆÜÑîâïàëè - ïðîäîëæàåìïðîñìîòðÎáðàçåö íà÷èíàåòñÿ ñ '?'Íàäî òîëüêî, ÷òîáû ñòðîêà íåêîí÷èëàñü (èíà÷å ËÎÆÜ)Ñèìâîëû ñîïîñòàâèëèñü =>ñäâèãàåìñÿ ïî ñòðîêå èîáðàçöó è ïðîäîëæàåìÑþäà ìû ïðûãàëè, ÷òîáûâåðíóòü ÈÑÒÈÍÓ;;;;;;;;;À ñþäà ïðûãàëè, ÷òîáûâåðíóòü ËÎÆÜÂñ¼, êîíåö ðàáîòûÏðèâîäèì âñ¼ âïîðÿäîê ïåðåäâîçâðàòîì óïðàâëåíèÿÐåçóëüòàò ó íàñ â EAXÂîçâðàùàåì óïðàâëåíèåÊÎÍÅÖ ÏÐÎÖÅÄÓÐÛÅñëè, íàïðèìåð, âàøà ñòðîêà ðàñïîëàãàåòñÿ â ïàìÿòè, ïîìå÷åííîéìåòêîé string, à îáðàçåö â ïàìÿòè, ïîìå÷åííîé ìåòêîé pattern, òîâûçîâ ïîäïðîãðàììû match áóäåò âûãëÿäåòü âîò òàê:push dword pattern89push dword stringcall matchadd esp, 8Ïîñëå ýòîãî ðåçóëüòàò ñîïîñòàâëåíèÿ (0 èëè 1) îêàæåòñÿ â ðåãèñòðå EAX.Îáðàòèòå âíèìàíèå, ÷òî â íà÷àëå ïîäïðîãðàììû ïðè ïîïûòêå ïåðåéòè íà ìåòêó .false ìû áûëè âûíóæäåíû ÿâíî óêàçàòü, ÷òî ïåðåõîä ÿâëÿåòñÿ áëèæíèì(near).
Äåëî â òîì, ÷òî ìåòêà .false îêàçàëàñü ÷óòü äàëüøå îò êîìàíäû ïåðåõîäà,÷åì ýòî äîïóñòèìî äëÿ êîðîòêîãî ïåðåõîäà. Ñì. îáñóæäåíèå íà ñòð. 60.¾¾¿¿ 2.7. Ñòðîêîâûå îïåðàöèèÄëÿ óïðîùåíèÿ âûïîëíåíèÿ äåéñòâèé íàä ìàññèâàìè (íåïðåðûâíûìèîáëàñòÿìè ïàìÿòè) ïðîöåññîð i386 ââîäèò íåñêîëüêî êîìàíä, îáúåäèíÿåìûõ â êàòåãîðèþ ñòðîêîâûõ îïåðàöèé . Èìåííî ýòè êîìàíäû èñïîëüçóþò ðåãèñòðû ESI è EDI â èõ îñîáîé ðîëè, îáñóæäàâøåéñÿ íà ñòð. 35.Îáùàÿ èäåÿ ñòðîêîâûõ êîìàíä ñîñòîèò â òîì, ÷òî ÷òåíèå èç ïàìÿòè âûïîëíÿåòñÿ ïî àäðåñó èç ðåãèñòðà ESI, çàïèñü â ïàìÿòü ïî àäðåñó èçðåãèñòðà EDI, à çàòåì ýòè ðåãèñòðû óâåëè÷èâàþòñÿ (èëè óìåíüøàþòñÿ) âçàâèñèìîñòè îò êîìàíäû íà 1, 2 èëè 4.
Íåêîòîðûå êîìàíäû ïðîèçâîäÿò÷òåíèå â ðåãèñòð èëè çàïèñü â ïàìÿòü èç ðåãèñòðà; â ýòîì ñëó÷àå èñïîëüçóåòñÿ ðåãèñòð ¾àêêóìóëÿòîð¿ ñîîòâåòñòâóþùåãî ðàçìåðà, òî åñòüðåãèñòð AL, AX èëè EAX. Ñòðîêîâûå êîìàíäû íå èìåþò îïåðàíäîâ, âñåãäàèñïîëüçóÿ îäíè è òå æå ðåãèñòðû.¾Íàïðàâëåíèå¿ èçìåíåíèÿ àäðåñîâ (äâèæåíèÿ âäîëü ñòðîê) îïðåäåëÿåòñÿ ôëàãîì DF (íàïîìíèì, åãî èìÿ îçíà÷àåò ¾direction ag¿, ò. å. ¾ôëàãíàïðàâëåíèÿ¿). Åñëè ýòîò ôëàã ñáðîøåí, àäðåñà óâåëè÷èâàþòñÿ (òî åñòüñòðîêîâàÿ îïåðàöèÿ âûïîëíÿåòñÿ ñëåâà íàïðàâî), åñëè ôëàã óñòàíîâëåí àäðåñà óìåíüøàþòñÿ (ñîîòâåòñòâåííî, ðàáîòàåì ñïðàâà íàëåâî).
Óñòàíîâèòü DF ìîæíî êîìàíäîé std (set direction), à ñáðîñèòü êîìàíäîé cld(clear direction).Ñàìûå ïðîñòûå èç ñòðîêîâûõ êîìàíä êîìàíäû stosb, stosw èstosd, êîòîðûå çàïèñûâàþò â ïàìÿòü ïî àäðåñó [edi], ñîîòâåòñòâåííî,áàéò, ñëîâî èëè äâîéíîå ñëîâî èç ðåãèñòðà AL, AX èëè EAX, ïîñëå ÷åãî óâåëè÷èâàþò èëè óìåíüøàþò (â çàâèñèìîñòè îò çíà÷åíèÿ DF) ðåãèñòð EDIíà 1, 2 èëè 4. Íàïðèìåð, åñëè ó íàñ åñòü ìàññèâbufresb 1024è íàì íóæíî çàïîëíèòü åãî íóëÿìè, ìû ìîæåì ïðèìåíèòü ñëåäóþùèéêîä:xor al, almov edi, buf; îáíóëÿåì al; àäðåñ íà÷àëà ìàññèâà90lp:mov ecx, 1024 ; äëèíà ìàññèâàcld; ðàáîòàåì â ïðÿìîì íàïðàâëåíèèstosb; al -> [edi], óâåë.
ediloop lpÝòè è äðóãèå ñòðîêîâûå êîìàíäû óäîáíî èñïîëüçîâàòü ñ ïðåôèêñîì rep.Êîìàíäà, ñíàáæåííàÿ òàêèì ïðåôèêñîì, áóäåò âûïîëíåíà ñòîëüêî ðàç,êàêîå ÷èñëî áûëî â ðåãèñòðå ECX (êðîìå êîìàíäû stosw: åñëè å¼ ñíàáäèòüïðåôèêñîì, òî áóäåò èñïîëüçîâàòüñÿ ðåãèñòð CX; ýòî îáóñëîâëåíî èñòîðè÷åñêèìè ïðè÷èíàìè). Ñ ïîìîùüþ ïðåôèêñà rep ìû ìîæåì ïåðåïèñàòüâûøåïðèâåä¼ííûé ïðèìåð áåç èñïîëüçîâàíèÿ ìåòêè:xormovmovcldrepal, aledi, bufecx, 1024stosbÊîìàíäû lodsb, lodsw è lodsd, íàîáîðîò, ñ÷èòûâàþò áàéò, ñëîâî èëèäâîéíîå ñëîâî èç ïàìÿòè ïî àäðåñó, íàõîäÿùåìóñÿ â ðåãèñòðå ESI, è ïîìåùàþò ïðî÷èòàííîå â ðåãèñòð AL, AX èëè EAX, ïîñëå ÷åãî óâåëè÷èâàþòèëè óìåíüøàþò çíà÷åíèå ðåãèñòðà ESI íà 1, 2 èëè 4.
Èñïîëüçîâàíèå ýòèõêîìàíä ñ ïðåôèêñîì rep îáû÷íî áåññìûñëåííî, ïîñêîëüêó ìû íå ñìîæåììåæäó ïîñëåäîâàòåëüíûìè èñïîëíåíèÿìè ñòðîêîâîé êîìàíäû âñòàâèòüêàêèå-òî åù¼ äåéñòâèÿ, îáðàáàòûâàþùèå çíà÷åíèå, ïðî÷èòàííîå è ïîìåù¼ííîå â ðåãèñòð. Îäíàêî èñïîëüçîâàíèå êîìàíä ñåðèè lods áåç ïðåôèêñà ìîæåò îêàçàòüñÿ âåñüìà ïîëåçíûì. Ïóñòü, íàïðèìåð, ó íàñ åñòü ìàññèâ÷åòûð¼õáàéòíûõ ÷èñåëarrayresd 256è íàì íåîáõîäèìî ñîñ÷èòàòü ñóììó åãî ýëåìåíòîâ.
Ýòî ìîæíî ñäåëàòüñëåäóþùèì îáðàçîì:lp:xor ebx,mov esi,mov ecx,cldlodsdadd ebx,loop lpebx; çàíóëÿåì ñóììóarray256eax×àñòî îêàçûâàåòñÿ óäîáíûì ñî÷åòàíèå êîìàíä ñåðèè lods ñ ñîîòâåòñòâóþùèìè êîìàíäàìè stos. Ïóñòü, íàïðèìåð, íàì íóæíî óâåëè÷èòü íà åäèíèöó âñå ýëåìåíòû òîãî æå ñàìîãî ìàññèâà. Ýòî ìîæíî ñäåëàòü òàê:91lp:mov esi, arraymov edi, esimov ecx, 256cldlodsdinc eaxstosdloop lpÅñëè æå íåîáõîäèìî ïðîñòî ñêîïèðîâàòü äàííûå èç îäíîé îáëàñòèïàìÿòè â äðóãóþ, î÷åíü óäîáíû îêàçûâàþòñÿ êîìàíäû movsb, movsw èmovsd.
Ýòè êîìàíäû êîïèðóþò áàéò, ñëîâî èëè äâîéíîå ñëîâî èç ïàìÿòèïî àäðåñó [esi] â ïàìÿòü ïî àäðåñó [edi], ïîñëå ÷åãî óâåëè÷èâàþò (èëèóìåíüøàþò) ñðàçó îáà ðåãèñòðà ESI è EDI (ñîîòâåòñòâåííî, íà 1, 2 èëè4). Íàïðèìåð, åñëè ó íàñ åñòü äâà ñòðîêîâûõ ìàññèâàbuf1buf2resb 1024resb 1024è íóæíî ñêîïèðîâàòü ñîäåðæèìîå îäíîãî èç íèõ â äðóãîé, ìîæíî ñäåëàòüýòî òàê:movmovmovcldrepecx, 1024esi, buf1edi, buf2movsbÁëàãîäàðÿ âîçìîæíîñòè èçìåíÿòü íàïðàâëåíèå ðàáîòû (ñ ïîìîùüþ DF),ìû ìîæåì ïðîèçâîäèòü êîïèðîâàíèå ÷àñòè÷íî ïåðåêðûâàþùèõñÿ îáëàñòåé ïàìÿòè.