Dos7book
.pdf
Глава 9: |
Примеры композиции исполняемых файлов |
|||
cmp byte ptr |
[005D],3F |
; 11A |
1-й байт - знак вопроса? |
|
jz |
0151 |
|
;*11F |
Если да, выведем help |
cld |
|
|
; 121 |
Зададим счет вверх (DF=UP) |
;********** Секция 2: Результаты поиска переменной |
||||
call |
0173 |
|
;*122 |
Вызовем подпрограмму поиска |
cmp byte ptr |
[0165],F7 |
; 125 |
Ошибки 1-го и 2-го циклов? |
|
ja |
0151 |
|
;*12A |
Выйдем, если имеются |
mov |
DX,0345 |
|
;*12C |
Введем адрес 2-го сообщения |
les |
DI,[00F8] |
; 12F |
Адрес переменной - в ES:DI |
|
ES: |
|
|
; 133 |
Считываем 1-й знак |
mov |
BL,[DI] |
|
; 134 |
значения переменной |
cmp |
BL,31 |
|
; 136 |
Нижняя граница: функция 1 |
jb |
0151 |
|
;*139 |
Выйдем, если значение меньше |
cmp |
BL,33 |
|
; 13B |
Верхняя граница: функция 3 |
ja |
0151 |
|
;*13E |
Выйдем, если значение больше |
shl |
BL,1 |
|
; 140 |
x2, т.к. адрес - это 2 байта |
mov |
BH,00 |
|
; 142 |
Подготовим BX к переходу |
call |
[BX+0105] |
;*144 |
Вызов основных функций |
|
jz |
0151 |
|
;*148 |
ZR - вывод сообщения |
jb |
015F |
|
;*14A |
CY - errorlevel èç DH |
;************* Секция 3: завершение программы.
;151 - переходы от 118, 11F, 12A, 139, 13E, 148
;15F - адрес перехода со строк 14A, 14F
call |
01F9 |
;*14C |
Подпрограмма копирования |
jmp |
015F |
;*14F |
Переход к завершению |
mov |
BX,DX |
;=151 |
DS:DX - адрес сообщения |
mov |
CX,[BX-02] |
; 153 |
CX = число знаков |
mov |
BX,0001 |
; 156 |
BX = ссылка на STDOUT |
mov |
AH,40 |
; 159 |
Вызов функции посылки |
int |
21 |
; 15B |
сообщения в STDOUT |
mov |
DH,F0 |
; 15D |
Errorlevel = F0h |
mov |
AL,DH |
;=15F |
Восстановим errorlevel |
mov |
AH,4C |
; 161 |
Вызов функции |
int |
21 |
; 163 |
завершения программы |
|
;************** Секция 4: блок данных. |
||
|
; 165 - адрес записи в 125, 1D1, 1D6, 1F4, 205 |
||
dw |
00FC |
|
|
;167 = (2*31 + 105) в строке 144, 221, 22D
;169 - в строках 225, 236, 240, 247, 252, 280 dw 0213,029A,02DC,0000,0000,0000
;************** Секция 5: поиск и проверка PSP
;173 - адрес вызова от строк 122, 1A3
;19F - адрес перехода со строки 197
;1A6 - переходы от строк 17A, 183, 18F, 19D
–512 –
Глава 9: |
Примеры композиции исполняемых файлов |
|||
xor |
DI,DI |
|
;=173 |
Обнулим регистр DI |
ES: |
|
|
; 175 |
Начинается ли сегмент |
cmp word ptr |
[DI],20CD |
; 176 |
с команды CD20? |
|
jnz |
01A6 |
|
;*17A |
Выйдем, если PSP не опознан |
ES: |
|
|
; 17C |
Имеется ли команда CD21 в |
cmp word ptr |
[0050],21CD |
; 17D |
ячейке 0050h? |
|
jnz |
01A6 |
|
;*183 |
Выйдем, если PSP не опознан |
push |
ES |
|
; 185 |
Сохраним адрес PSP |
ES: |
|
|
; 186 |
Загрузим сегментный адрес |
mov |
ES,[002C] |
; 187 |
окружения в регистр ES |
|
call |
01B3 |
|
; 18B |
Подпрограмма поиска имени |
pop |
ES |
|
; 18E |
Восстановим адрес PSP в ES |
jz |
01A6 |
|
;*18F |
Выйдем, если имя не найдено |
mov |
AX,ES |
|
; 191 |
Сегментный адрес PSP - в AX |
mov |
DI,0016 |
|
; 193 |
Равен ли адрес в ES:[0016] |
scasw |
|
|
; 196 |
адресу данного PSP в AX? |
jnz |
019F |
|
;*197 |
Если нет, это PSP-родитель |
mov |
DI,0010 |
|
; 199 |
Равен ли адрес в ES:[0010] |
scasw |
|
|
; 19C |
адресу данного PSP в AX? |
jz |
01A6 |
|
;*19D |
Если да, ничего мы не нашли |
ES: |
|
|
;=19F |
Загрузим в ES сегментный |
mov |
ES,[DI-02] |
; 1A0 |
адрес родительского PSP |
|
call |
0173 |
|
; 1A3 |
Вызовем проверку этого PSP |
ret |
|
|
;=1A6 |
Возврат из подпрограммы |
;************* Секция 6: подпрограмма поиска имени
;1A7 - адрес перехода со строк 1C8, 1CF
;1B3 - адрес вызова со строки 18B
;1DF - адрес перехода со строк 1B1, 1BA
mov |
CX,0100 |
;=1A7 |
Зададим число |
сравнений |
mov |
AL,00 |
; 1AA |
Сравниваем со |
значением 00 |
repnz |
|
; 1AC |
Повтор, пока не найдем 00 |
|
scasb |
|
; 1AD |
Сравниваем [ES:DI] с AL=00 |
|
cmp |
CX,0000 |
; 1AE |
Если число сравнений |
|
jz |
01DF |
;*1B1 |
исчерпано, |
кончаем поиск |
mov |
DX,0318 |
;=1B3 |
Точка входа в |
цикл поиска |
ES: |
|
; 1B6 |
Если [DI]==00h, значит |
|
cmp byte ptr |
[DI],00 |
; 1B7 |
окружение просмотрено |
|
jz |
01DF |
;*1BA |
все, кончаем поиск |
|
mov |
SI,005D |
; 1BC |
Адрес имени - |
â DS:SI |
mov |
CX,000A |
; 1BF |
Зададим число |
сравнений в CX |
repz |
|
; 1C2 |
Повтор до первого различия |
|
cmpsb |
|
; 1C3 |
Сравниваем [DS:SI] с [ES:DI] |
|
cmp byte ptr |
[SI-01],20 |
; 1C4 |
Имя кончается |
пробелом? |
jnz |
01A7 |
;*1C8 |
Перейдем к следующему имени |
|
|
|
|
– 513 – |
|
Глава 9: |
Примеры композиции исполняемых файлов |
|||
ES: |
|
|
; 1CA Стоит ли после имени |
|
cmp byte ptr |
[DI-01],3D |
; 1CB |
знак равенства? |
|
jnz |
01A7 |
|
;*1CF Перейдем к следующему имени |
|
sub byte ptr |
[0165],04 |
;*1D1 Сдвиг адреса записи |
||
mov |
SI,[0165] |
;*1D6 Адрес записи - в регистр SI |
||
mov |
[SI],DI |
|
; 1DA Адрес значения переменной |
|
mov |
[SI+02],ES |
; 1DC Сегментный адрес окружения |
||
ret |
|
|
;=1DF Возврат из подпрограммы |
|
;******** Секция 7: подпрограмма копирования
;1E0 - адрес перехода со строки 210
;1E5 - адрес перехода со строки 1F1
;1F3 - адрес перехода со строк 1E9, 1EE
;1F9 - адрес вызова со строки 14C
;1FB - адрес перехода со строки 202
;204 - адрес перехода со строки 1FF
CS: |
|
;=1E0 |
Загрузим |
адрес источника |
lds |
SI,[00F8] |
; 1E1 |
|
в регистры DS:SI |
ES: |
|
;=1E5 |
Есть ли еще место |
|
cmp byte ptr |
[DI],00 |
; 1E6 |
ïî |
адресу назначения? |
jz |
01F3 |
;*1E9 |
Åñëè íåò |
- в следующий цикл |
cmp byte ptr |
[SI],00 |
; 1EB |
Есть ли знаки в источнике? |
|
jz |
01F3 |
;*1EE |
Åñëè íåò |
- в следующий цикл |
movsb |
|
; 1F0 |
Скопируем один байт |
|
jmp |
01E5 |
;*1F1 |
Проверим |
следующий байт |
CS: |
|
;=1F3 |
Сменим адрес |
|
add word ptr |
[0165],0004 |
; 1F4 |
назначения |
|
mov |
AL,20 |
;=1F9 |
Точка входа в подпрограмму |
|
ES: |
|
;=1FB |
Есть ли место |
|
cmp byte ptr |
[DI],00 |
; 1FC |
по адресу заполнения? |
|
jz |
0204 |
;*1FF |
Если нет, кончим заполнять |
|
stosb |
|
; 201 |
Пробел - |
в адрес назначения |
jmp |
01FB |
;*202 |
Проверим |
следующий байт |
CS: |
|
;=204 |
Загрузим |
номер |
mov |
SI,[0165] |
; 205 |
|
ячейки в SI |
CS: |
|
; 209 |
Загрузим |
адрес назначения |
les |
DI,[SI] |
; 20A |
|
в регистры ES:DI |
cmp |
SI,00F8 |
; 20C |
Номер ячейки - последний? |
|
jnz |
01E0 |
;*210 |
Åñëè íåò |
- возврат в цикл |
ret |
|
; 212 |
Возврат из подпрограммы |
|
;****** Секция 8: функция 1, объем XMS-памяти
;213 - адрес вызова в ячейке 167
;256 - адрес перехода со строк 23E, 247, 250
;25B - адрес перехода со строки 263
;269 - адрес перехода со строки 277
–514 –
Глава 9: Примеры композиции исполняемых файлов
;275 - адрес перехода со строки 272
;284 - адрес перехода со строки 27E
;285 - адрес перехода со строк 21A, 234
mov |
AX,4300 |
;=213 |
Точка входа в функцию 1 |
int |
2F |
; 216 |
Проверим, установлен ли |
cmp |
AL,80 |
; 218 |
XMS-драйвер Himem.sys? |
jnz |
0285 |
;*21A |
Выйдем, если не установлен |
mov |
AX,4310 |
; 21C |
Запрос адреса вызова |
int |
2F |
; 21F |
Адрес вызова - в ES:BX |
mov |
[0167],BX |
; 221 |
Смещения адреса вызова |
mov |
[0169],ES |
; 225 |
Сегмент адреса вызова |
mov |
BL,00 |
; 229 |
Зададим 00h в регистре BL |
mov |
AH,08 |
; 22B |
Код запроса объема |
call far |
[0167] |
; 22D |
Запрос к Himem.sys |
cmp |
BL,00 |
; 231 |
Запрос исполнен успешно? |
jnz |
0285 |
;*234 |
Выйдем, если не успешно |
mov byte ptr |
[0169],00 |
; 236 |
Зададим errorlevel = 00 |
cmp |
AX,1900 |
; 23B |
если XMS-памяти для |
jb |
0256 |
;*23E |
6 Mb диска недостаточно |
inc byte ptr |
[0169] |
; 240 |
Зададим errorlevel = 01 |
cmp |
AX,4900 |
; 244 |
åñëè 5600 Kb XMS-äèñê |
jb |
0256 |
;*247 |
может быть создан |
inc byte ptr |
[0169] |
; 249 |
Зададим errorlevel = 02 |
cmp |
AX,8C00 |
; 24D |
если XMS-диск ограничен |
jb |
0256 |
;*250 |
объемом 16 Mb, а если |
inc byte ptr |
[0169] |
; 252 |
íåò, òî errorlevel = 03 |
mov |
BP,SP |
;=256 |
Фиксируем состояние SP |
mov |
BX,000A |
; 258 |
Зададим делитель |
xor |
DX,DX |
;=25B |
Очистим DX перед делением |
div |
BX |
; 25D |
Разделим на 0Ah |
push |
DX |
; 25F |
Затолкнем остаток в стек |
cmp |
AX,0000 |
; 260 |
Процесс деления закончен? |
jnz |
025B |
;*263 |
Если нет - следующий цикл |
les |
DI,[00F8] |
; 265 |
Адрес переменной - в ES:DI |
pop |
AX |
;=269 |
Вытолкнем разряд из стека |
add |
AL,30 |
; 26A |
Переведем цифру в код ASCII |
mov |
SI,DI |
; 26C |
SI фиксирует факт записи |
ES: |
|
; 26E |
Есть ли свободное место |
cmp byte ptr |
[DI],00 |
; 26F |
по адресу назначения? |
jz |
0275 |
;*272 |
Обойдем запись, если нет |
stosb |
|
; 274 |
Запишем цифру, увеличим DI |
cmp |
SP,BP |
;=275 |
Все остатки вытолкнуты? |
jb |
0269 |
;*277 |
Если нет, вытолкнем еще |
mov |
DX,036F |
;*279 |
3-е сообщение об ошибке |
|
|
|
– 515 – |
|
Глава 9: |
Примеры композиции исполняемых файлов |
||||
cmp |
DI,SI |
|
; 27C Áûëà ëè |
запись пропущена? |
||
jz |
0284 |
|
;*27E |
|
|
|
mov |
DH,[0169] |
; 280 Считаем |
errorlevel â DH |
|||
ret |
|
|
;=284 |
|
|
|
mov |
DH,FF |
|
;=285 Errorlevel |
= FF |
||
stc |
|
|
; 287 |
Завершение |
с ошибкой |
|
ret |
|
|
; 288 |
Возврат |
èç |
подпрограммы |
;******* Секция 9: функция 2, ввод с клавиатуры
;289 - адрес перехода со строки 2AD
;29A - переходы от 169, 28D, 291, 295, 2B4, 2BD
;2BF - адрес перехода со строки 2A8
;2C7 - адрес перехода со строк 2A3, 2C3
ES: |
|
;=289 |
Сначала проверим, |
cmp byte ptr |
[DI],00 |
; 28A |
заполнен ли буфер |
jz |
029A |
;*28D |
Åñëè äà, æäåì 1Bh, 0Dh, 08h |
cmp |
AL,20 |
; 28F |
Знаки ниже 20h в |
jb |
029A |
;*291 |
переменную не вводим |
cmp |
AL,3D |
; 293 |
Знак равенства в |
jz |
029A |
;*295 |
переменную не вводим |
int |
29 |
; 297 |
Отобразим введенный знак |
stosb |
|
; 299 |
Копируем знак в буфер ES:DI |
mov |
AH,10 |
;=29A |
Точка входа в функцию 2 |
int |
16 |
; 29C |
Считываем знак с клавиатуры |
mov |
DH,FF |
; 29E |
Errorlevel = FFh |
cmp |
AH,01 |
; 2A0 |
Нажата ли клавиша ESC? |
jz |
02C7 |
;*2A3 |
Если да, то не копируем |
cmp |
AH,1C |
; 2A5 |
Нажата ли клавиша ENTER? |
jz |
02BF |
;*2A8 |
Если да, выходим и копируем |
cmp |
AH,0E |
; 2AA |
Нажата клавиша BackSpace? |
jnz |
0289 |
;*2AD |
Если нет, вернемся в цикл |
ES: |
|
; 2AF |
Проверим, не будет ли адрес |
cmp byte ptr |
[DI-01],3D |
; 2B0 |
в регистре DI указывать |
jz |
029A |
;*2B4 |
на точку до начала буфера |
mov |
AX,2008 |
; 2B6 |
Вывод знака возврата и |
call |
02D2 |
;*2B9 |
пробела через INT 29 |
dec |
DI |
; 2BC |
Уменьшим указатель в DI |
jmp |
029A |
;*2BD |
Вернемся к началу цикла |
cmp |
DI,[00F8] |
;=2BF |
Изменилось ли число в DI? |
jz |
02C7 |
;*2C3 |
Если нет, оставим DH = FFh |
mov |
DH,00 |
; 2C5 |
Если да, установим DH = 00 |
mov |
AX,0A0D |
;=2C7 |
Вывод знаков перевода |
call |
02D2 |
;*2CA |
строки через INT 29 |
cmp |
DH,20 |
; 2CD |
Установим флаги |
cmc |
|
; 2D0 |
Реверсируем флаг переноса |
|
|
|
– 516 – |
Глава 9: Примеры композиции исполняемых файлов
ret |
|
; 2D1 |
Возврат из подпрограммы |
|
;***** Секция 10: функция 2, подпрограмма вывода |
||
|
; 2D2 - адрес вызова со строк 2B9, 2CA |
||
|
; 2D5 - адрес возврата в цикле со строки 2D9 |
||
mov |
CX,0003 |
;=2D2 |
Установим число повторений |
int |
29 |
;=2D5 |
Выведем знак на экран |
xchg |
AL,AH |
; 2D7 |
Обменяем коды знаков |
loop |
02D5 |
;*2D9 |
Проверим условие цикла |
ret |
|
; 2DB |
Возврат из подпрограммы |
|
;***** Секция 11: функция 3, определение буквы диска |
||
;2DC - записан в ячейку 16B
;2EE - адрес перехода со строки 2E9
;2F6 - адрес перехода со строки 30C
;305 - адрес перехода со строки 2FE
;30E - адрес перехода со строк 2F9 и 308
mov |
AH,19 |
;=2DC |
Точка входа в функцию 3 |
int |
21 |
; 2DE |
Определим текущий диск |
mov |
DL,AL |
; 2E0 |
Скопируем номер диска в DL |
add |
AL,41 |
; 2E2 |
Преобразуем в букву диска |
stosb |
|
; 2E4 |
Скопируем букву в ES:DI |
ES: |
|
; 2E5 |
и увеличим число в DI |
cmp byte ptr |
[DI],00 |
; 2E6 |
Проверим, заполнен ли буфер |
jz |
02EE |
;*2E9 |
Если да, не добавим ":" |
mov |
AL,3A |
; 2EB |
Введем код ":" в AL |
stosb |
|
; 2ED |
Скопируем ":" в буфер ES:DI |
mov |
DH,00 |
;=2EE |
Предустановим errorlevel |
push |
DI |
; 2F0 |
Сохраним DI в стеке |
mov |
AX,0803 |
; 2F1 |
Запрос адреса 1-й DDT |
int |
2F |
; 2F4 |
Адрес 1-й DDT - в DS:DI |
cmp |
[DI+04],AL |
;=2F6 |
Это флоппи-диск? |
ja |
030E |
;*2F9 |
Если нет, то дальше не ищем |
cmp |
[DI+04],AH |
; 2FB |
Если дисковод тот же, |
jz |
0305 |
;*2FE |
то его не учитываем |
mov |
AH,[DI+04] |
; 300 |
Запомним номер дисковода |
inc |
DH |
; 303 |
Увеличим число дисководов |
cmp word ptr |
[DI],FFFF |
;=305 |
Данная DDT - последняя? |
jz |
030E |
;*308 |
Если да, то дальше не ищем |
lds |
DI,[DI] |
; 30A |
Адрес следующей DDT в DS:DI |
jmp |
02F6 |
;*30C |
Исследуем DDT дальше |
pop |
DI |
;=30E |
Восстановим DI |
push |
CS |
; 30F |
Восстановим первоначальное |
pop |
DS |
; 310 |
состояние DS |
cmp |
DH,FF |
; 311 |
Сбросим флаг ZF в NZ |
clc |
|
; 314 |
Сбросим флаг переноса |
|
|
|
– 517 – |
