jumps
.286
.model small
.code
org 100h
start:  sub sp, 4
        pusha
        push ds
        push es
        call $+13
        rIP1    dw offset pass_error
        rCS1    dw 0
        rIP2    dw 100h
        rCS2    dw 0
        rlcCnt  dw 0
        pop si

        push cs
        pop ax

        mov ds, ax
        mov es, ax
        mov di, ax 

        sub di, word ptr cs:[si+6]
;        mov word ptr cs:[si+6], di
        add di, word ptr cs:[si+2]
        mov ax, word ptr cs:[si]
        lea bp, cs:[si-9]

        mov ds:[bp+offset rpCS-100h], di
        mov ds:[bp+offset rpIP-100h], ax

        mov ah, 09h
        lea dx, ds:[bp+offset enter_pass-100h]
        int 21h

        ; Read password from stdin
        ;-------------------------------
        lea di, ds:[bp+offset pass-100h]
        mov cx, 20
chrloop:mov ah, 08h
        int 21h
        cmp al, 0Dh
        jz pass_end
        stosb
        mov ah, 02h
        mov dl, '*'
        int 21h
        dec cx
        jnz chrloop
pass_end:
        mov ah, 09h
        lea dx, ds:[bp+offset newline-100h]
        int 21h
        sub cx, 20
        neg cx
        mov ds:[bp+offset pass_len-100h], cx
        test cx, cx
        jz pass_error
        ;-----------------------------------
        ; Done

        ;Decode test string (to check password validity) and relocation table
        ;--------------------------------------------------------------------
        lea di, ds:[bp+offset test_pass-100h]
        mov cx, 9
        call decode
        ;----------
        ;Done

        ;Check password validity
        ;------------------------------------
        lea di, ds:[bp+offset test_pass-100h]
        mov cx, 10
        xor ax, ax
        xor bx, bx
loop_check:
        mov bl, [di]
        add al, bl
        inc di
        loop loop_check

        test al, al
        jnz pass_error
        ;-------------
        ; Password OK!

        ; Decode reloc table
        lea di, ds:[bp+offset reloc-100h]
        mov cx, ds:[si+8]

bg_reloc_loop:
        cmp cx, 100
        jb lst_reloc

        push cx
        mov cx, 399
        push di
        call decode
        pop di
        call submagic

        call alignESDI
        pop cx
        sub cx, 100
        jmp bg_reloc_loop
lst_reloc:
        shl cx, 2
        dec cx
        push di
        call decode
        pop di
        call submagic

        push cs
        pop es

        ;Start decoding program
        ;----------------------
        mov cx, cs:[si+6]       ; First, we need to calculate size of coded prog
        mov ax, cs:[si+4]
        mov bx, cx
        shr cx, 12
        and bx, 0FFFh
        shl bx, 4
        add bx, ax
        adc cx, 0               ; In cx:bx we got host size

        push cs
        pop ax
        sub ax, word ptr cs:[si+6]
        mov cs:[si+6], ax
        mov es, ax                      
        xor di, di              ; In es:di we've got offset to prog begin

        ;First - decode full segments (0xFFFF length)
seg_loop:
        test cx, cx
        jz resudary_part
        push cx
        xor cx, cx
        not cx
        call decode
        call submagic

        mov ax, es      
        add ax, 1000h
        mov es, ax
        pop cx
        dec cx
        jmp seg_loop
resudary_part:
        mov cx, bx
        dec cx
        call decode
        xor di, di
        call submagic

        ; Substitite relocation table
        ;----------------------------
        push cs
        pop es
        mov cx, ds:[si+8]       ; Relo item count
        mov bx, ds:[si+6]
        lea di, ds:[bp+offset reloc-100h]
relowork:
        call alignESDI
        mov si, es:[di]
        mov ax, es:[di+2]
        add ax, bx
        mov ds, ax
        add word ptr ds:[si], bx
        add di, 4        
        loop relowork

        
        ;Normal return to parent proc
        ;----------------------------
        push ss
        pop es
        push sp
        pop di
        mov ax, cs:[bp+offset rpIP-100h]
        mov es:[di+14h], ax
        mov ax, cs:[bp+offset rpCS-100h]
        mov es:[di+16h], ax
        pop es
        pop ds
        popa
        retf
        ;-----------------------------
        ; Done!
;---------------------------------
pass_error:
        mov ah, 09h
        lea dx, ds:[bp+offset bad_pass-100h]
        int 21h
        mov ax, 4CFFh
        int 21h                        
;------------------
; es:di - what to decode
; cx - length
decode proc near 
        push si
        push ax
        push cx
loops2: lea si, ds:[bp+offset pass-100h]
        cmp cx, ds:[bp+offset pass_len-100h]
        jb lasts2
        push cx
        mov cx, ds:[bp+offset pass_len-100h]
addmag2: mov al, ds:[si]
        xor es:[di], al
        inc si
        inc di
        loop addmag2
        pop cx
        sub cx, ds:[bp+offset pass_len-100h]
        jmp loops2

lasts2: inc cx
lasts3: mov al, ds:[si]
        xor es:[di], al
        inc si
        inc di
        loop lasts3

        pop cx
        pop ax
        pop si
        ret
endp

submagic proc near 
        push si
        push ax
        push cx
loops:  lea si, ds:[bp+offset test_pass-100h]
        cmp cx, 10
        jb lasts
        push cx
        mov cx, 10
addmag: mov al, ds:[si]
        sub es:[di], al
        inc si
        inc di
        loop addmag
        pop cx
        sub cx, 10
        jmp loops

lasts:  inc cx
lasts0: mov al, ds:[si]
        sub es:[di], al
        inc si
        inc di
        loop lasts0

        pop cx
        pop ax
        pop si
        ret
endp
;------------------
alignESDI proc near
        push ax
        push cx
        mov ax, di
        shr ax, 4
        mov cx, es
        add ax, cx
        mov es, ax
        and di, 0Fh
        pop cx
        pop ax
        ret
endp
;----------------------
rpIP    dw 0
rpCS    dw 0
newline db 0dh, 0ah, '$'
enter_pass db 'Please enter pass: $'
bad_pass db 'Sorry, you''ve entred a bad password',0Dh,0Ah,'$'
pass    db 20 dup (0)
pass_len dw 0
test_pass db 10, 12, 15, 17, -20, -13, 05, -30, 55, -51
reloc   dd ?
end start