текстовый режим по умолчанию -80x50 (см. закоментированную строчку в коде). граббер никак не
выгружается -в данном случае не это реализовывать требовалось -достаточно закрыть dos -сессию.
Code: Select all
; простенькая хваталка содержимого экрана (183bytes).
.186
model tiny
.code
; по умолчанию все числа в шестнадцатеричной системе.
.radix 16
org 0100
; ------
; инсталлер.
; получаем адрес входа в i16 (bios kbd services)
@grab:
mov ax,3516
@sav2:
int 21
; сохраняем его в начало программы. код на cs:0100 более не нужен.
mov word ptr ds:[@grab],bx
mov word ptr ds:[@grab+02],es
; перехватываем i16.
lea dx,@kbd
mov ax,2516
int 21
; все до метки @fnsh в память и завершаем работу инсталлера.
lea dx,@fnsh
int 27
; ------
; видеоэффект "граббер активен". дважды переXORеваем видеопамять.
@izvr:
call $+03
mov cx,4000d
@izvr2:
mov bx,cx
xor es:[bx],cl
loop @izvr2
retn
; мы сами не отслеживаем моменты когда можно проверить "а не нажата ли клавиша".
; доверяем хосту, т.е. работающей в данный момент программе.
; если хост и операционка находятся в состоянии готовности, они непременно вызовут нас.
@kbd:
pushf ;;
; ah=0, keyboard read (debug.exe)
; ah=10, extended read (dos navigator etc)
or ah,ah
jz @kbd2
cmp ah,10
jz @kbd2
popf ;;
; выход. отдать упр-е старому обработчику.
jmp dword ptr cs:[@grab]
; вызов биос i16 "что за клавиша была нажата"
; флажки уже в стеке.
@kbd2:
call dword ptr cs:[@grab]
; сравниваем с нашим hotkey.
; если отличен от "`" (клавиша между tab и esc) мы отдаем упр-е хосту.
cmp al,60
jz @fukk
iret
; здесь начинается непосредственно захват :).
@fukk:
pusha ;;
push ds es ;;
push 0b800 ;;
pop es ;;
; после видеоэффекта cx равен 0 (loop).
call @izvr
; откроем "gtab.dta"
; работа ведется в нашем кодовом сегменте.
mov ax,3d02
push cs ;;
pop ds ;;
lea dx,_file
int 21
; если файла не существует (на readonly проверять не зачем), создадим заново.
jnb @allok
mov ah,3c
int 21
; сохраним на будущее рукоять файла в bp.
@allok:
xchg bx,ax
mov bp,bx
; если файл уже существует, мы станем добавлять в конец.
; для этого смещаем указатель чтения // записи.
mov ax,4202
cwd ; синонимично sub dx,dx
int 21
sub bx,bx
@main:
sub cx,cx
@ltl:
; мини -цикл
; в al попадает ascii код символа с экрана
; bx -смещение
mov al,es:[bx]
; адресуемся отн. регистра cx
xchg bx,cx
; используем место отработавшего кода инсталлера под данные.
; смещение @sav2 плюс один байт, чтобы не накрыть адрес старого i16
mov byte ptr ds:[@sav2+01+bx],al
xchg bx,cx
; следующий байт видеопамяти -атрибут символа.
; нам он не нужен.
inc bx
inc bx
; мини -цикл за один проход берет по 20 байт.
inc cx
cmp cl,20d ;значение не менять! (можно затереть код tsr -части)
jnz @ltl
push bx ;;
; пишем сгенерированную строчку символов в grab.dta
; cl=20d, в bp хендл файла.
mov ah,40
mov bx,bp
lea dx,@sav2+01
int 21
; в стеке было сохраненено текущее смещение в видеопамяти.
; при делении на 160d (80x2) проверяем остаток от деления.
pop ax ;;
push ax ;;
mov bl,160d
div bl
; достигнут "конец" данной строки экрана.
or ah,ah
jnz @crlf
; добавляем 0d0a (crlf).
mov cl,02
mov ah,40
mov bx,bp
lea dx,_crlf
int 21
; проверяем, не исчерпали мы всю видеопамять.
; если нет, вызываем мини -цикл.
@crlf:
pop bx ;;
cmp bx,8000d ;for 80x25 -change to 4000d
jnz @main
; закрываем файл.
mov bx,bp
mov ah,3e
int 21
; восстанавливаем содержимое регистров и завершаемся.
; выемка кода горячей клавиши из буфера не происходит.
pop es ds ;;
popa ;;
iret
; немного данных.
_file db "grab.dta",00
_crlf dw 0a0dh
@fnsh:
end @grab
tlink /x/t grab50.obj