;--------------------------------------------------;
; file intlist.asm                                 ; 
; visualizza i 256 vettori di interruzione         ;
;--------------------------------------------------;
; nasm -f obj intlist.asm -l intlist.lst           ;
; tlink /t intlist.obj + comlib.obj                ;
; (oppure link /map /tiny intlist.obj + comlib.obj);
;--------------------------------------------------;                  

;########### direttive per l'assembler ############

CPU 386                             ; set di istruzioni a 32 bit
%include "comlib.inc"               ; inclusione libreria di I/O

;######### dichiarazione tipi e costanti ##########

%assign  MAX_INTS    256            ; numero totale INT.

;################ segmento unico ##################

SEGMENT     COMSEGM ALIGN=16 PUBLIC USE16 CLASS=CODE

   resb     0100h                   ; libera 256 byte per il PSP
   
..start:                            ; entry point

;------- inizio blocco principale istruzioni ------

   call     set80x50                ; modo video testo 80x50
   call     hideCursor              ; nasconde il cursore
   call     clearScreen             ; pulisce lo schermo

; mostra la stringa del titolo

   mov      di, strTitle            ; ds:di punta a strTitle
   mov      dx, 000Eh               ; riga 0, colonna 14
   call     writeString             ; mostra la stringa

; mostra la stringa delle informazioni

   mov      di, strInfo             ; ds:di punta a strInfo
   mov      dx, 2300h               ; riga 35, colonna 0
   call     writeString             ; mostra la stringa

; inizializza FS:SI = 0000h:0000h per l'accesso ai vettori di interruzione

   xor      ax, ax                  ; ax = 0
   mov      fs, ax                  ; fs = Seg(0000h)
   xor      si, si                  ; si = Offset(0000h)

; loop principale del programma

   mov      word [int_counter], 0      ; inizializza il contatore INT

main_loop:
   mov      word [row_counter], 0200h  ; inizializza il contatore riga
   mov      cx, 32                     ; mostra 32 INT per volta
  
int_loop:
   call     show_interrupt             ; visualizza il prossimo INT
   inc      word [int_counter]         ; incremento contatore INT
   add      word [row_counter], 0100h  ; incremento riga
   add      si, 4                      ; prossimo vettore di INT
   loop     int_loop                   ; se (cx maggiore di 0) ripeti

   cmp      word [int_counter], MAX_INTS ; compara int_counter con MAX_INTS
   jb       continua                   ; se e' minore salta a continua
   mov      word [int_counter], 0      ; riazzera int_counter
   xor      si, si                     ; riazzera SI (0000h)

continua:
   call     waitChar                   ; attende la pressione di un tasto
   cmp      al, 20h                    ; premuto [SPAZIO] = ASCII(20h) ?
   je       main_loop                  ; si
   cmp      al, 1Bh                    ; premuto [ESC] = ASCII(1Bh) ?
   jne      continua                   ; tasto non valido

   call     clearScreen                ; pulisce lo schermo
   call     showCursor                 ; ripristina il cursore

;-------- fine blocco principale istruzioni -------
   
   mov      ah, 4ch                 ; servizio Terminate Program
   mov      al, 00h                 ; exit code = 0
   int      21h                     ; chiama i servizi DOS

;----- inizio definizione variabili statiche ------

   align 4, db    0                 ; allinea alla DWORD

int_counter dw    0                 ; contatore INT
row_counter dw    0                 ; contatore riga
   
strTitle    db    'VETTORI DI INTERRUZIONE DEL PC (Formato Seg:Offset)', 0
strLine     db    'INT n. XXh = XXXXh:', 0
strInfo     db    '[SPAZIO] = continua, [ESC] = fine', 0

;------- fine definizione variabili statiche ------

;---------- inizio definizione procedure ----------

show_interrupt:

; mostra la stringa delle interruzioni

   mov      di, strLine             ; ds:di punta a strLine
   mov      dx, [row_counter]       ; dx = coordinate di output
   call     writeString             ; mostra la stringa

; mostra il numero della INT

   mov      ax, [int_counter]       ; ax = contatore INT
   mov      dl, 07h                 ; colonna 7
   call     writeHex8               ; mostra in n. della INT

; mostra la coppia Seg:Offset della INT

   mov      ax, [fs:si+2]           ; ax = componente Seg
   mov      dl, 0Dh                 ; colonna 13
   call     writeHex16              ; mostra la componente Seg

   mov      ax, [fs:si+0]           ; ax = componente Offset
   mov      dl, 13h                 ; colonna 19
   call     writeHex16              ; mostra la componente Offset

   ret                              ; NEAR return
   
;----------- fine definizione procedure -----------

;##################################################