─[CPU EXTENDER]─────────────────────────────────────────────────[UAZZ KLINGUN]─


   описание cpu extender'а

    Итак, что это такое и для чего он нужен. При написании  сей  приблуды было
 поставлено несколько задач:

  - Упростить написание некоторые  частоупотребимых  операций, используемых  в
    вирях (например чтение/запись  файла, передвижение по нему и т.д.). Раньше
    ведь как надо было? поместить handle в bx, ds:dx поставить на буфер и т.д.
    С  использованием  Extender'a  жизнь  упрощается (звучит почти как реклама
    Win95/98/00). Теперь можно в программе просто записать _read ax,4000,cs,si
    (где в ax расположился  handle, в cs:si указатель на код, и 4000 - р-р чи-
    таемого блока. Точно такими же  свойствами обладают и все остальные опера-
    ции, поддерживаемые Extender`ом. Причем, почти все (за исключением  одной)
    операции работают в резидентных приложениях :).

  - Затруднить работу дизасемблерам и эвристикам. Теперь в вире практически не
    будут встречаться  прямые вызовы многих операций. По листингу  вообще зат-
    руднительно будет понять смысл написанного. Эвристики  скорее всего  также
    заткнуться (но не эмуляторы). Правда, счастье  вечным не будет (пока у них
    не появиться данный код).

  - Затруднить работу отладчиков реального режима. Для этой цели  проходят че-
    рез  вызов  int 3h (что это  такое, думаю, объяснять  не надо :)). Правда,
    всвязи  с  решением работать через это прерывание, у меня  случился спор с
    одним  человеком на тему  того, может ли то, что  представлено ниже, назы-
    ваться CPU Extender'ом. Он мотивировал это тем, что Extender должен  дейс-
    твовать через прерывание Invalid Opcode (т.е. через int 6h). Ну ладно, это
    к делу не  относится, но в принципе вы можете сами выбирать, на  какой int
    это дело повесить.


   как все это должно работать?

    Теперь краткое описание того, как все это работает (должно работать) Нача-
 ло программы должно выглядеть примерно так:

include extend.asm
begin:
       mov ax,2503h
       push cs
       pop ds
       mov dx,offset int_03h     ;Наименование процедуры обработки
       int 21h
       _init                     ;Для доступа к файловым опрациям

    Ну вот и все, теперь  можете  использовать Extender на полную катушку. Для
 того, чтобы его использовать, необходимо знать синтаксис вызова макросов. Для
 тех, кому будет  лень копаться в исходнике и кто хочет его  просто  использо-
 вать, я привожу  требуемую  информацию. Замечание: все  параметры (кроме imm)
 передаются через регистры.

_random      r16                     ; Заносит случайное значение в указанный
                                     ; регистр (кроме ss и ip). Оччень
                                     ; интересный эффект даст _random cs :))
_move        ss16,so16,ds16,do16,imm16   ; Перемещает блок размером imm16
                                     ; с места указанного в регистрах
                                     ; ss16:so16 на место ds16:do16
                                     ; Пример _move cs,dx,cs,si,100h
                                     ; С cs:di в cs:si
_set_vect    imm8,s16,o16            ; Установить вектор номер imm8
                                     ; Процедура обработки в s16:o16
_get_vect    imm8,r16,r16            ; Аналогично, только получить адрес
                                     ; обработчика
_open_file   s16,o16,imm8,h16        ; Открытие файла, имя файла в s16:o16
				     ; Режим доступа в imm8
				     ; возвращает handle в h16	(при неудачном
				     ; открытии handle=0
_close_file  r16                     ; Закрытие файла с указанным handlom
_seek        h16,imm8,l16,h16,l16,h16; перемещение по файлу h16, режим 
				     ; перемещения (от начала, от конца, от
				     ; текущей позиции) - imm8
				     ; младшая:старшая части смещения,
				     ; возвращаются также младшая:старшая
				     ; части смещения
_read        h16,imm16,s16,o16       ; Чтение из файла h16 imm16 байт в буфер
				     ; s16:016	
_write       h16,imm16,s16,o16       ; Тоже самое, только запись
_disable_timer                       ; Запрещает прерывания от таймера
_enable_timer                        ; разрешает прерывания от таймера
_xor         s16,o16,c16,imm16       ; Хорит код начиная с s16:o16 количеством
				     ; с16 с ключом imm16	
_init                                ; без параметров (использование см. пример)

    Итак, описание приведено.  В файле extend.asm содержится исходный код суб-
 жа, в файле ext.asm - мааленький примерчик. Все остальное зависит от вас.

────[EXT.ASM]────────[START]───────────────────────────────────────────────────
c_seg segment public
      assume cs:c_seg
include extend.asm
beg:
     push cs
     pop ds
     mov dx,offset int_03h    ;Обязательно произвести усановку 3-го инта
     mov ax,2503h             ;на процедуру int_03h
     int 21h
     _init
     mov ax,1234h
     mov bx,4321h
     _random ax
     _random bx
     mov dx,offset txt
     mov ah,9
     int 21h
     mov ax,dx
     add ax,100h
     _move cs,dx,cs,ax,len
     mov dx,ax
     mov ah,9
     int 21h
     mov ax,4c00h
     int 21h
txt  db 'Это просто тест',10,13,'$'
len equ $-offset txt
c_seg ends
end beg
────[EXT.ASM]────────[EOF]─────────────────────────────────────────────────────

────[EXTEND.ASM]─────[START]───────────────────────────────────────────────────
;CPU Extender  (c)Uazz Klingun (по мотивам John Darland'a)
;Version 0.0.1
;For 16-bit registers only
.286

_ext macro
     db 0cch,90h
     ;db 0cdh,60h,90h
endm

opEcs   equ 18
opEax   equ 14
opEbx   equ 12
opEcx   equ 10
opEdx   equ 8
opEsi   equ 6
opEdi   equ 4
opEds   equ 2
opEes   equ 0

opRandom        equ 01h  ;_random      r16
opMove          equ 02h  ;_move        r16,r16,r16,r16,imm16
opSet_vect      equ 03h  ;_set_vect    imm8,r16,r16
opGet_vect      equ 04h  ;_get_vect    imm8,r16,r16
opOpen_file     equ 05h  ;_open_file   r16,r16,r16
opClose_file    equ 06h  ;_close_file  r16
opSeek          equ 07h  ;_seek        r16,imm8,r16,r16,r16,r16
opRead          equ 08h  ;_read        r16,imm16,r16,r16
opWrite         equ 09h  ;_write       r16,imm16,r16,r16
opDis_timer     equ 0ah  ;_disable_timer
opEnb_timer     equ 0bh  ;_enable_timer
opXor           equ 0ch  ;_xor         r16,r16,r16,imm16
opInit_21h      equ 0fh  ;_init

_reg            macro r1
        ifidn <r1>, <ax>
          db opEax
        endif
        ifidn <r1>, <bx>
          db opEbx
        endif
        ifidn <r1>, <cx>
          db opEcx
        endif
        ifidn <r1>, <dx>
          db opEdx
        endif
        ifidn <r1>, <si>
          db opEsi
        endif
        ifidn <r1>, <di>
          db opEdi
        endif
        ifidn <r1>, <ds>
          db opEds
        endif
        ifidn <r1>, <es>
          db opEes
        endif
        ifidn <r1>, <cs>
          db opEcs
        endif
endm

_random macro r16
        _ext
        db opRandom
        _reg r16
endm

_move macro r1,r2,r3,r4,i1   ;ds:si,es:di,cx(imm16)
      _ext
      db opMove
      _reg r1
      _reg r2
      _reg r3
      _reg r4
      dw i1
endm

_set_vect macro i1,r1,r2      ;Number of vector,seg,ofs
          _ext
          db opSet_vect
          db i1
          _reg r1             ;seg
          _reg r2             ;ofs
endm

_get_vect macro i1,r1,r2
          _ext
          db opGet_vect
          db i1
          _reg r1
          _reg r2
endm

_open_file macro r1,r2,i1,r3 ;ds:dx,imm8,bx  ;Any registers in this content
           _ext              ;      ^^^^ - mode
           db opOpen_file
           _reg r1
           _reg r2
           db i1
           _reg r3
endm

_close_file macro r1         ;bx
            _ext
            db opClose_file
            _reg r1
endm

_seek macro r1,i1,r2,r3,r4,r5        ;bx,al,dx(lo),cx(hi)
            _ext                     ;return (lo) (hi)
            db opSeek
            _reg r1
            db i1
            _reg r2
            _reg r3
            _reg r4
            _reg r5
endm

_read macro r1,i1,r2,r3              ;bx,count,ds:dx
      _ext
      db opRead
      _reg r1
      dw i1
      _reg r2
      _reg r3
endm

_write macro r1,i1,r2,r3
       _ext
       db opWrite                    ;bx,count,ds:dx
       _reg r1
       dw i1
       _reg r2
       _reg r3
endm

_disable_timer macro
               _ext
               db opDis_timer
endm

_enable_timer macro
              _ext
              db opEnb_timer
endm

_xor macro r1,r2,r3,i1          ;ds:si,cx,cheap
     _ext
     db opXor
     _reg r1
     _reg r2
     _reg r3
     dw i1
endm

_init macro
      _ext
      db opInit_21h
endm

_es     equ 0
_ds     equ 2
_di     equ 4
_si     equ 6
_dx     equ 8
_cx     equ 10
_bx     equ 12
_ax     equ 14
_ip     equ 16
_cs     equ 18
_flags  equ 20

int_03h proc
        push ax
        push bx
        push cx
        push dx
        push si
        push di
        push ds
        push es
        push bp
        mov bp,sp
        add bp,2
        mov bx,ss:[bp+_cs]
        mov es,bx
        mov bx,ss:[bp+_ip]
        cmp byte ptr es:[bx],90h
        je @0
        jmp Not_Our_Call
@0:
        inc bx
        inc bx                        ; bx теперь указывает на 1-й параметр
        mov al,byte ptr es:[bx-1]
        cmp al,opRandom
        jne @1
        call random
        jmp @f
@1:
        cmp al,opMove
        jne @2
        call move
        jmp @f
@2:
        cmp al,opSet_vect
        jne @3
        call set_vect
        jmp @f
@3:
        cmp al,opGet_vect
        jne @4
        call get_vect
        jmp @f
@4:
        cmp al,opOpen_file
        jne @5
        call open_file
        jmp @f
@5:
        cmp al,opClose_file
        jne @6
        call close_file
        jmp @f
@6:
        cmp al,opSeek
        jne @7
        call seek
        jmp @f
@7:
        cmp al,opRead
        jne @8
        call read
        jmp @f
@8:
        cmp al,opWrite
        jne @9
        call write
        jmp @f
@9:
        cmp al,opDis_timer
        jne @a
        call dis_timer
        jmp @f
@a:
        cmp al,opEnb_timer
        jne @b
        call enb_timer
        jmp @f
@b:
        cmp al,opXor
        jne @e
        call @xor
        jmp @f
@e:
        cmp al,opInit_21h
        jne @f
        call init
@f:

Not_Our_Call:
        pop bp
        pop es
        pop ds
        pop di
        pop si
        pop dx
        pop cx
        pop bx
        pop ax
        iret
int_03h endp

__1 proc near               ;В cx возвращает содержимое регистра
    push ax
    xor ax,ax
    mov al,byte ptr es:[bx]
    add bp,ax
    mov cx,word ptr ss:[bp]
    sub bp,ax
    inc bx
    pop ax
    ret
__1 endp

__2 proc near     ;На входе сx - число,которое необходимо записать
    push ax
    xor ax,ax
    mov al,byte ptr es:[bx]
    add bp,ax
    mov word ptr ss:[bp],cx
    sub bp,ax
    inc bx
    pop ax
    ret
__2 endp

__3 proc near      ;Вызов 21-го инта
    push bp
sh1:
    call $+3
    pop bp
    sub bp,3
    pushf
    call dword ptr cs:[bp][offset int_21h-offset sh1]
    pop bp
    ret
__3 endp

random proc near
       in al,40h
       xchg ah,al
       in al,40h
       mov dl,byte ptr es:[bx]
       xor dh,dh
       add bp,dx
       mov word ptr ss:[bp],ax
       sub bp,dx
       add word ptr ss:[bp+_ip],1+2
       ret
random endp

move proc near    ;ds:si,es:di,cx(imm)
     call __1
     mov ds,cx
     call __1
     mov si,cx
     call __1
     mov es,cx
     call __1
     mov di,cx
     mov cx,word ptr es:[bx]
rep  movsb
     add word ptr ss:[bp+_ip],6+2
     ret
move endp

set_vect proc near  ;imm8,ds:dx
         xor ax,ax
         mov ds,ax
         mov dl,byte ptr es:[bx]
         shl dl,2
         mov si,dx
         call __1
         mov word ptr ds:[si+1],cx
         call __1
         mov word ptr ds:[si],cx
         add word ptr ss:[bp+_ip],3+2
         ret
set_vect endp

get_vect proc near  ;imm8,ds:dx
         xor ax,ax
         mov ds,ax
         mov dl,byte ptr es:[bx]
         shl dl,2
         mov si,dx
         mov cx,word ptr ds:[si+1]
         call __2
         mov cx,word ptr ds:[si]
         call __2
         add word ptr ss:[bp+_ip],3+2
         ret
get_vect endp

open_file proc near       ;ds:dx,imm8,bx    Только для _существующих_ файлов!
          call __1        ;Перед вызовом _ЛЮБОЙ_ функции работы с файлом
          mov ds,cx       ;должна вызываться функция _init (один раз
          call __1        ;на всю программу)
          mov dx,cx
          mov al,byte ptr es:[bx]
          inc bx
          mov ah,3dh
          call __3
          jnc ok1
          xor bx,bx
ok1:
          mov cx,bx
          call __2
          add word ptr ss:[bp+_ip],4+2
          ret
open_file endp

close_file proc near
           call __1
           mov bx,cx
           mov ah,3eh
           call __3
           add word ptr ss:[bp+_ip],1+2
           ret
close_file endp

seek proc near           ;bx,al,dx,cx,(lo),(hi)
     call __1            ;   ^^-imm (mode 00/01/02)
     push cx
     mov al,byte ptr es:[bx]
     mov ah,42h
     push ax
     inc bx
     call __1
     push cx
     call __1
     pop dx
     pop ax
     pop bx
     call __3
     mov cx,ax
     call __2
     mov cx,dx
     call __2
     add word ptr ss:[bp+_ip],6+2
     ret
seek endp

read proc near           ;bx,count,ds:dx
     call __1
     mov ax,cx
     mov cx,word ptr es:[bx]
     inc bx
     inc bx
     push cx
     call __1
     mov ds,cx
     call __1
     mov dx,cx
     pop cx
     mov bx,ax
     mov ah,3fh
     call __3
     add word ptr ss:[bp+_ip],5+2
     ret
read endp

write proc near                   ;bx,count,ds:dx
      call __1
      mov ax,cx
      mov cx,word ptr es:[bx]
      inc bx
      inc bx
      push cx
      call __1
      mov ds,cx
      call __1
      mov dx,cx
      pop cx
      mov bx,ax
      mov ah,40h
      call __3
      add word ptr ss:[bp+_ip],5+2
      ret
write endp

dis_timer proc near
          in al,21h
          or al,1
          out 21h,al
          add word ptr ss:[bp+_ip],0+2
          ret
dis_timer endp

enb_timer proc near
          in al,21h
          and al,0feh
          out 21h,al
          add word ptr ss:[bp+_ip],0+2
          ret
enb_timer endp

@xor proc near                         ;ds:si,cx,cheap
     call __1
     mov ds,cx
     call __1
     mov si,cx
     call __1
     mov ax,word ptr es:[bx]
ag1:
     xor word ptr ds:[si],ax
     inc si
     inc si
     loop ag1
     add word ptr ss:[bp+_ip],5+2
     ret
@xor endp

init proc near
     mov ax,3521h
     int 21h
     push bp
sh2:
     call $+3
     pop bp
     sub bp,3
     mov word ptr cs:[bp][offset int_21h-offset sh2],bx
     mov word ptr cs:[bp][offset int_21h-offset sh2+2],es
     pop bp
     add word ptr ss:[bp+_ip],0+2
     ret
init endp

int_21h dw ?
        dw ?
────[EXTEND.ASM]─────[EOF]─────────────────────────────────────────────────────

                                 (c) Uazz KlinGun, soldier of Misdirected Youth