Пример анализа операционной среды DOS
С помощью функции EnvString вы сможете просмотреть операционную среду DOS и найти строку вида "s=НЕЧТО" и возвратить НЕЧТО, если это найдено.
DATA SEGMENT PUBLIC EXTRN prefixSeg : Word ; дает адрес PSP DATA ENDS SEGMENT PUBLIC ASSUME cs:CODE,ds:DATA
EnvString PROC FAR PUBLIC EnvString push bp cld ; работать в прямом направлении mov es,[prefixSeg] ; посмотреть PSP mov es,es:[2Ch] ; ES:DI указывают на операционную среду, xor di,di ; которая выровнена на границу параграфа mov bp,sp ; найти строку параметров, lds si,ss:[bp+6] ; которая следует за ; адресом возврата ASSUME ds:NOTHING lodsb ; посмотреть длину or al,al ; она равна 0? jz RetNul ; да, возврат mov ah,al ; в противном случае ; сохранить ее в AH mov dx,si ; DS:SI содержат указатель ; на первый параметр ; char xor al,al ; сделать его равным 0 Compare: mov ch,al ; мы хотим, чтобы для ; следующего отсчета ch=0 mov si,dx ; возвратить указатель на ; просмотренную строку mov cl,ah ; получить длину mov si,dx ; возвратить указатель на ; строку repe cmpsb ; сравнить байты jne Skip ; если сравнение неудачное попробовать следующую строку cmp byte ptr es:[di],"=" ; сравнение завершилось успешно следующий символ "="? jne NoEqual ; если нет, все еще нет совпадения Found: mov ax,es ; DI:SI будет указывать ; на найденную нами строку mov ds,ax mov si,di inc si ; "пройти" символ "=" les bx,ss:[bp+10] ; получить адрес результата функции mov di,bx ; занести его в ES:DI inc di ; байт длины mov cl,255 ; задать максимальную длину CopyLoop: lodsb ; получить байт or al,al ; проверить на 0 jz Done ; если 0, выполнено stosb ; занести его в результат loop CopyLoop ; переместить до 255 байт Done: not cl ; при сохранении мы уменьшали от CL до 255 mov es:[bx],cl ; сохранить длину mov ax,SEG DATE mov ds,ax ; восстановить DS ASSUME ds:DATA pop bp ret 4 ASSUME ds:NOTHING Skip: dec di ; проверить на 0 NoEqual: mov cx,7FFFh ; длинный поиск, если нужно sub cx,di ; операционная среда никогда не превышает 32К jbe RetNul ; если конец, выйти repne scasb ; посмотреть следующий 0 jcxz RetNul ; выйти, если не найден cmp byte ptr es:[di],al ; второй 0 в строке? jne Compare ; если нет, попытаться снова RetNul: les di,ss:[bp+10] ; получить адрес результата stosb ; сохранить там 0 mov ax,SEG DATA mov ds,ax ; восстановить DS ASSUME ds:DATA pop bp ret 4 EnvString ENDP CODE ENDS END
Программа на Паскале, которая использует функцию EnvString, выглядит следующим образом:
program EnvTest; { программа ищет строки операционной среды }
var EnvVariable : string; EnvValue : string;
{$F+}
function EnvString(s:string) : string; external; {$L ENVSTRING.OBJ} {$F-} begin EnvVariable := "PROMPT"; EnvValue := EnvString(EnvVariable); if EnvValue = "" then EnvValue := "*** не найдена ***"; Writeln("Переменная операционной среды: ", EnvVariable," Значение: ",EnvValue); end.
Чтобы сформировать и запустить данные программы на Паскале и Ассемблере, используйте следующие команды командного файла:
TASM ENVSTR TPC ENVTEST ENVTEST
Если использовать директиву .MODEL, то функция EnvString на Ассемблере будет выглядеть следующим образом (ENVMOD.ASM):
.MODEL large, PASCAL .DATA EXTRN prefixSeg : Word ; дает адрес PSP .CODE EnvString PROC FAR EnvVar:DWORD RETURNS EnvVal:DWORD PUBLIC EnvString push bp cld ; работать в прямом направлении mov es,[prefixSeg] ; посмотреть PSP mov es,es:[2Ch] ; ES:DI указывают на операционную среду, xor di,di ; которая выровнена на границу параграфа mov bp,sp ; найти строку параметров, lds si,ss:[bp+6] ; которая следует за адресом возврата ASSUME ds:NOTHING lodsb ; посмотреть длину or al,al ; она равна 0? jz RetNul ; да, возврат mov ah,al ; в противном случае ; сохранить ее в AH mov dx,si ; DS:SI содержат указатель ; на первый параметр ; char xor al,al ; сделать его равным 0 Compare: mov ch,al ; мы хотим, чтобы для следующего отсчета ch=0 mov si,dx ; возвратить указатель на просмотренную строку mov cl,ah ; получить длину mov si,dx ; возвратить указатель на ; строку repe cmpsb ; сравнить байты jne Skip ; если сравнение неудачное, попробовать следующую строку cmp byte ptr es:[di],"=" ; сравнение завершилось успешно следующий символ "="? jne NoEqual ; если нет, все еще нет совпадения Found: mov ax,es ; DI:SI будет указывать на найденную нами строку mov ds,ax mov si,di inc si ; "пройти" символ "=" les bx,ss:[bp+10] ; получить адрес результата функции mov di,bx ; занести его в ES:DI inc di ; байт длины mov cl,255 ; задать максимальную длину CopyLoop: lodsb ; получить байт or al,al ; проверить на 0 jz Done ; если 0, выполнено stosb ; занести его в результат loop CopyLoop ; переместить до 255 байт Done: not cl ; при сохранении мы уменьшали от CL до 255 mov es:[bx],cl ; сохранить длину mov ax,SEG DATE mov ds,ax ; восстановить DS ASSUME ds:DATA pop bp ret 4 ASSUME ds:NOTHING Skip: dec di ; проверять на 0 NoEqual: mov cx,7FFFh ; длинный поиск, если нужно sub cx,di ; операционная среда никогда не превышает 32К jbe RetNul ; если конец, выйти repne scasb ; посмотреть следующий 0 jcxz RetNul ; выйти, если не найден cmp byte ptr es:[di],al ; второй 0 в строке? jne Compare ; если нет, попытаться снова RetNul: les di,ss:[bp+10] ; получить адрес результата stosb ; сохранить там 0 mov ax,SEG DATA mov ds,ax ; восстановить DS ASSUME ds:DATA ret 4 EnvString ENDP CODE ENDS END
Вы можете использовать ту же программу на Паскале и просто ассемблировать альтернативный вариант функции EnvString и перекомпилировать программу с помощью того же командного файла.
1 2 3 4 5 6 7 8
8 8 8
|