;   ** Initialize
;      Close all the doors.

init:
mov bx,offset doors     ; Load in BX the starting offset
                        ;of the doors data.
xor ax,ax               ; Set the AX register with
                        ;0000: close two doors (a byte=a door=
                        ;00, two bytes=a word=two doors=0000)
                        ;This pass is done by XORing the word
                        ;in AX by itself, clearing it to zero.
                        ;This occupies two bytes in memory,
                        ;instead of the four needed for
                        ;the equivalent operation mov ax,0000h.
mov cl,032h             ; Set CL to 50 decimal = 32 hex.
                        ;The half of 100 because we will
                        ;write two bytes at once, closing
                        ;two doors and reducing the time needed
                        ;to do the task.

initloop:
mov [bx],ax             ; Close two doors (write a 0000 word).
inc bx                  ; Increment the pointer.
inc bx
dec cl                  ; Decrement the counter.
jnz initloop            ; Loop or else fall through.

;   ** Main
;      Do toggle the doors in memory.
;       The non optimized program output shows that the open
;      rooms are separed by a number of closed rooms that's
;      the number of doors opened so far multiplied by two.
;       The formula is:
;      p+(i*2)+1
;      where p is the last door found and i is the number of
;      doors opened so far. When recursively applied with
;      p=i=0 in the first step, this formula will produce a list
;      of perfect squares of integer numbers:
;      1=0+(0*2)+1
;      4=1+(1*2)+1
;      9=4+(2*2)+1
;      16=9+(3*2)+1
;       This program does use this approach for speeding the
;      calculations instead of calculating the perfect squares
;      by the usual method (x*x), to save the time needed to
;      reinitialize the index every time.

dodoor:
xor cx,cx               ; Set the CX register to 0000.
mov bx,offset doors-1   ; Set the pointer BX to the doors
                        ;address minus one because otherwise
                        ;zero would count as one ("doors"
                        ;points to the first door).
doorloop:
add bx,cx               ; Set the BX address to BX + (CX * 2) + 1
add bx,cx               ;This sets the address of the door to
inc bx                  ;open.
mov [bx],0FFh           ; Open the door overwriting his
                        ;byte with the new one.
inc cl                  ; Increment the counter register CX
cmp cl,0Ah              ; If cl is not 10 (in fact 11 because zero
jnz doorloop            ;counts), we didn't finish, then loop.

programend:             ; The above loop does fall here when it
                        ;ends.
cli                     ; Clear the interrupt flag, disabling
                        ;any software and most of the hardware
                        ;interrupts (the maskable interrupts).
hlt                     ; Freeze the processor.
jmp programend          ; If a Non Maskable Interrupt does pull
                        ;the CPU from his freezed state, do
                        ;freeze it again.

doors:                  ; Pointer to the end of the program,
                        ;where the RAM space is free to keep the
                        ;100 doors bytes.