jumps
.286
cseg segment byte public 'CODE'
        assume cs:cseg, ds:cseg, es:cseg
start:
        mov ax, seg cseg
        mov es, ax
        push ax

        mov si, 80h
        cmp byte ptr ds:[si], 0
        je errusg
        xor ax, ax
        mov al, ds:[si]
        dec ax
        mov cx, ax
        inc si
        inc si

        mov di, offset _hname

lp:     cmp byte ptr ds:[si], 0dh
        je wrk
        movsb
        loop lp

wrk:    pop ds

;------------- Host --------------------
        mov ax, 3d02h
        mov dx, offset _hname
        int 21h
        jc IOErr
        mov bx, ax
        mov handle, ax

        mov ah, 3fh
        mov dx, offset header
        mov cx, 28
        int 21h
;------------- Host --------------------

;------- Password ----------------------
        mov ah, 09h
        mov dx, offset enter_pass
        int 21h
        ; Read password from stdin
        ;-------------------------------
        lea di, [pass]
        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
        mov dx, offset newline
        int 21h
        sub cx, 20
        neg cx
        mov [pass_len], cx
        cmp cx, 3
        jl pass_error
        ;-----------------------------------
        ; Done

;------------- Header ------------------
        mov ax, 'CD'                    ; Set signature
        mov [header+12h], ax
;------------- Header ------------------

        ; Write EXE header
        mov ax, 4200h
        mov bx, handle
        xor cx, cx
        xor dx, dx
        int 21h

        mov ah, 40h
        mov cx, 28
        mov dx, offset header
        int 21h

        ; Calculate count of encode bytes
        mov ax, 4202h
        xor cx, cx
        xor dx, dx
        int 21h

        mov cx, dx      ; Hi part
        mov dx, ax      ; Lo part

        assume cs:cseg, ds:dseg, es:dseg
        mov ax, seg dseg
        mov es, ax
        mov ds, ax
        
        mov bx, cs:[header+8]
        mov ax, bx
        shr ax, 12
        mov cs:[lastOffsH], ax
        shl bx, 4
        mov cs:[lastOffsL], bx

        sub cx,[lastOffsH] 
        sub dx,[lastOffsL] 

        mov bx, [handle]

        push dx        
seg_loop:
        test cx, cx
        jz no_seg

begins: push cx
;        push dx        
        mov ax, 4200h
        mov cx, cs:[lastOffsH]        
        mov dx, cs:[lastOffsL]
        int 21h

        mov ah, 3Fh     ; Read segment of 
        mov cx, 0ffffh  ; input file
        mov dx, 0       ;
        int 21h         ;
        mov ah, 3Fh     ; Read segment of 
        mov cx, 1h      ; input file
        mov dx, 0ffffh  ;
        int 21h         ;

        xor di, di
        xor cx, cx
        not cx
        call addmagic
        call encode

        mov ax, 4200h
        mov cx, cs:[lastOffsH]        
        mov dx, cs:[lastOffsL]
        int 21h

        mov ah, 40h     ; Write segment to
        mov cx, 0FFFFh   ; the input file
        mov dx, 0       ;
        int 21h         ;
        mov ah, 40h     ; Write segment to
        mov dx, 0FFFFh   ; the input file
        mov cx, 1       ;
        int 21h         ;

        inc cs:[lastOffsH]

        pop cx
        dec cx
        jmp seg_loop

no_seg: 
        mov ax, 4200h
        mov cx, cs:[lastOffsH]        
        mov dx, cs:[lastOffsL]
        int 21h
        mov ah, 3Fh     ; Read data of 
        pop cx          ; input file
        push cx
        mov dx, 0       ;
        int 21h         ;

        xor di, di
        pop cx
        push cx
        dec cx
        call addmagic
        xor di, di
        call encode

        mov ax, 4200h
        mov cx, cs:[lastOffsH]        
        mov dx, cs:[lastOffsL]
        int 21h

        mov ah, 40h     ; Write segment to
        pop cx
        mov dx, 0       ;
        int 21h         ;

        pop dx
        ; Close host file
        mov ah, 3eh
        int 21h
        ;- Done
;--------------------------------------------------        
        mov ah, 4ch
        int 21h
;--------------------------------------------------
;==================================================
;--------------------------------------------------
pass_error:
        mov dx, offset bad_pass
        mov ah, 09h
        int 21h

        mov ax, 4cFFh
        int 21h
errusg: pop ds
        mov ah, 09h
        mov dx, offset errstr
        int 21h
        mov ax, 4cFEh
        int 21h

IOErr: mov ah, 09h
        mov dx, offset errstr
        int 21h
        mov ax, 4cFDh
        int 21h

;-----------------------------------------------
encode proc near 
        push si
        push ax
        push cx
loops2: mov si, offset pass
        cmp cx, cs:[pass_len]
        jb lasts2
        push cx
        mov cx, cs:[pass_len]
addmag2: mov al, cs:[si]
        xor es:[di], al
        inc si
        inc di
        loop addmag2
        pop cx
        sub cx, cs:[pass_len]
        jmp loops2

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

        pop cx
        pop ax
        pop si
        ret
endp

addmagic proc near 
        push si
        push ax
        push cx
loops:  mov si, offset test_pass
        cmp cx, 10
        jb lasts
        push cx
        mov cx, 10
addmag: mov al, cs:[si]
        add es:[di], al
        inc si
        inc di
        loop addmag
        pop cx
        sub cx, 10
        jmp loops

lasts:  inc cx
lasts0: mov al, cs:[si]
        add es:[di], al
        inc si
        inc di
        loop lasts0

        pop cx
        pop ax
        pop si
        ret
endp

test_pass db 10, 12, 15, 17, -20, -13, 05, -30, 55, -51
io_err_str      db 'Error in file io', 0dh, 0ah, '$'
enter_pass db 'Please enter pass: $'
errstr     db 'usage: "coder.exe source"', 0dh, 0ah,'$'
_hname          db 13 dup (0)
bad_pass        db 'Bad password',0dh,0ah,'$'
newline         db 0dh,0ah,'$'
zeroBuf         db 400 dup (0)
pass            db 20 dup (0)
pass_len        dw ?
handle          dw ?
header          dw 14 dup (?)
_isize          dw ?
lastOffsH       dw ?
lastOffsL       dw ?
rCS2            dw ?
rIP2            dw ?
reloBuf         dw 200 dup (?)
buffer          dw 07B00h dup (?)
ends
dseg segment para public 'DATA'
file_buf db 0FFFFh dup (?)
ends
sseg segment stack
 db 200 dup (?)
ends
end start