;--------------------------------------------------;
; file jmp.asm                                     ; 
; programma di esempio per l'istruzione JMP        ;
;--------------------------------------------------;
; nasm -f obj jmp.asm -l jmp.lst                   ;
; tlink jmp.obj + exelib.obj                       ;
; (oppure link /map jmp.obj + exelib.obj)          ;
;--------------------------------------------------;                  

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

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

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

%assign STACK_SIZE   0400h          ; 1024 byte per lo stack

;################ segmento dati ###################

SEGMENT     DATASEGM ALIGN=16 PUBLIC USE16 CLASS=DATA

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

label_addr16   dw    0
label_addr32   dd    0

strCode1       db    'CODESEGM =', 0
strCode2       db    'LIBCODE  =', 0

strMsg1        db    'JMP diretto intrasegmento (SHORT)         - '
               db    'da      :      a      :', 0
strMsg2        db    'JMP diretto intrasegmento (NEAR)          - '
               db    'da      :      a      :', 0
strMsg3        db    'JMP indiretto intrasegmento (Reg16)       - '
               db    'da      :      a      :', 0
strMsg4        db    'JMP indiretto intrasegmento (Mem16)       - '
               db    'da      :      a      :', 0
strMsg5        db    'JMP diretto intersegmento (Ptr16:Ptr16)   - '
               db    'da      :      a      :', 0
strMsg6        db    'JMP indiretto intersegmento (Mem16:Mem16) - '
               db    'da      :      a      :', 0

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

;############### segmento codice ##################

SEGMENT     CODESEGM ALIGN=16 PUBLIC USE16 CLASS=CODE

..start:                            ; entry point

   mov      ax, DATASEGM            ; trasferisce DATASEGM
   mov      ds, ax                  ; in DS attraverso AX

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

   call     far set80x25            ; modo video 80 righe, 25 colonne
   call     far clearScreen         ; pulisce lo schermo

   push     ds                      ; copia DS
   pop      es                      ; in ES (per writeString)

; ATTENZIONE! Se si ha la necessita' di modificare ES, bisogna preservarne
; il vecchio contenuto; la procedura writeString presuppone, infatti, che
; ES contenga la componente Seg dell'indirizzo della stringa da visualizzare!

; mostra i valori assegnati dal SO a CODESEGM e LIBCODE

   mov      di, strCode1            ; di = offset strCode1
   mov      dx, 0400h               ; riga 4, colonna 0
   call     far writeString         ; mostra la stringa

   mov      ax, CODESEGM            ; ax = CODESEGM
   mov      dx, 040Bh               ; riga 4, colonna 11
   call     far writeHex16          ; mostra ax

   mov      di, strCode2            ; di = offset strCode2
   mov      dx, 0500h               ; riga 5, colonna 0
   call     far writeString         ; mostra la stringa

   mov      ax, LIBCODE             ; ax = LIBCODE
   mov      dx, 050Bh               ; riga 5, colonna 11
   call     far writeHex16          ; mostra ax

; JMP diretto intrasegmento (SHORT)

orig_label1:                        ; 003Dh
   jmp      short dest_label1       ; 003Dh  EBh 2Ah
   
return_label1:                      ; 003Fh

; JMP diretto intrasegmento (NEAR)

orig_label2:                        ; 003Fh
   jmp      near dest_label2        ; 003Fh  E9h 01BEh

return_label2:                      ; 0042h

; JMP indiretto intrasegmento (Reg16)

   mov      cx, dest_label3         ; 0042h  B9h [023Ah]
orig_label3:                        ; 0045h
   jmp      cx                      ; 0045h  FFh E1h

return_label3:                      ; 0047h

; JMP indiretto intrasegmento (Mem16)

   mov      ax, dest_label4         ; 0047h  B8h [0274h]
   mov      [label_addr16], ax      ; 004Ah  A3h [0000h]
orig_label4:                        ; 004Dh
   jmp      [label_addr16]          ; 004Dh  FFh 26h [0000h]

return_label4:                      ; 0051h

; JMP diretto intersegmento (Ptr16:Ptr16)

orig_label5:                        ; 0051h
   jmp      far dest_label5         ; 0051h  EAh [0000h][0000h]

return_label5:                      ; 0056h

; JMP indiretto intersegmento (Mem16:Mem16)

   mov      ax, dest_label6               ; 0056h  B8h [003Ch]
   mov      word [label_addr32+0], ax     ; 0059h  A3h [0002h]
   mov      ax, seg dest_label6           ; 005Ch  B8h [0000h]
   mov      word [label_addr32+2], ax     ; 005Fh  A3h [0004h]
orig_label6:                              ; 0062h
   jmp      far [label_addr32]            ; 0062h  FFh 2Eh [0002h]

return_label6:                      ; 0066h

   jmp      exit_label              ; 0066h  E9h 0245h

;---------------------------------------------------

; destinazione del JMP diretto intrasegmento (SHORT)

dest_label1:                        ; 0069h
   mov      di, strMsg1             ; 0069h  BFh [001Ch]
   mov      dx, 0700h               ; 006Ch  BAh [0700h]
   call     far writeString         ; 006Fh  9Ah [0000h][0000h]

   mov      ax, seg orig_label1     ; 0074h  B8h [0000h]
   mov      dx, 072Fh               ; 0077h  BAh 072Fh
   call     far writeHex16          ; 007Ah  9Ah [0000h][0000h]

   mov      ax, orig_label1         ; 007Fh  B8h [003Dh]
   mov      dx, 0735h               ; 0082h  BAh 0735h
   call     far writeHex16          ; 0085h  9Ah [0000h][0000h]

   mov      ax, seg dest_label1     ; 008Ah  B8h [0000h]
   mov      dx, 073Dh               ; 008Dh  BAh 073Dh
   call     far writeHex16          ; 0090h  9Ah [0000h][0000h]

   mov      ax, dest_label1         ; 0095h  B8h [0069h]
   mov      dx, 0743h               ; 0098h  BAh 0743h
   call     far writeHex16          ; 009Bh  9Ah [0000h][0000h]

   jmp      short return_label1     ; 00A0h  EBh 9Dh

; avanza il location counter a CODESEGM:0200h

   times    0200h - ($ - $$) db 0   ; offset = 512 byte

; destinazione del JMP diretto intrasegmento (NEAR)

dest_label2:                        ; 0200h
   mov      di, strMsg2             ; 0200h  BFh [0060h]
   mov      dx, 0800h               ; 0203h  BAh 0800h
   call     far writeString         ; 0206h  9Ah [0000h][0000h]

   mov      ax, seg orig_label2     ; 020Bh  B8h [0000h]
   mov      dx, 082Fh               ; 020Eh  BAh 082Fh
   call     far writeHex16          ; 0211h  9Ah [0000h][0000h]

   mov      ax, orig_label2         ; 0216h  B8h [003Fh]
   mov      dx, 0835h               ; 0219h  BAh 0835h
   call     far writeHex16          ; 021Ch  9Ah [0000h:0000h]
   
   mov      ax, seg dest_label2     ; 0221h  B8h [0000h]
   mov      dx, 083Dh               ; 0224h  BAh 083Dh
   call     far writeHex16          ; 0227h  9Ah [0000h][0000h]

   mov      ax, dest_label2         ; 022Ch  B8h [0200h]
   mov      dx, 0843h               ; 022Fh  BAh 0843h
   call     far writeHex16          ; 0232h  9Ah [0000hh][0000h]

   jmp      return_label2           ; 0237h  E9h FE08h

; destinazione del JMP indiretto intrasegmento (Reg16)

dest_label3:                        ; 023Ah
   mov      di, strMsg3             ; 023Ah  BFh [00A4h]
   mov      dx, 0900h               ; 023Dh  BAh 0900h
   call     far writeString         ; 0240h  9Ah [0000h][0000h]

   mov      ax, seg orig_label3     ; 0245h  B8h [0000h]
   mov      dx, 092Fh               ; 0248h  BAh 092Fh
   call     far writeHex16          ; 024Bh  9Ah [0000h][0000h]

   mov      ax, orig_label3         ; 0250h  B8h [0045h]
   mov      dx, 0935h               ; 0253h  BAh 0935h
   call     far writeHex16          ; 0256h  9Ah [0000h][0000h]

   mov      ax, seg dest_label3     ; 025Bh  B8h [0000h]
   mov      dx, 093Dh               ; 025Eh  BAh 093Dh
   call     far writeHex16          ; 0261h  9Ah [0000h][0000h]

   mov      ax, dest_label3         ; 0266h  B8h [023Ah]
   mov      dx, 0943h               ; 0269h  BAh 0943h
   call     far writeHex16          ; 026Ch  9Ah [0000h][0000h]
   
   jmp      return_label3           ; 0271h  E9h FDD3h

; destinazione del JMP indiretto intrasegmento (Mem16)

dest_label4:                        ; 0274h
   mov      di, strMsg4             ; 0274h  BFh [00E8h]
   mov      dx, 0A00h               ; 0277h  BAh 0A00h
   call     far writeString         ; 027Ah  9Ah [0000h][0000h]

   mov      ax, seg orig_label4     ; 027Fh  B8h [0000h]
   mov      dx, 0A2Fh               ; 0282h  BAh 0A2Fh
   call     far writeHex16          ; 0285h  9Ah [0000h][0000h]

   mov      ax, orig_label4         ; 028Ah  B8h [004Dh]
   mov      dx, 0A35h               ; 028Dh  BAh 0A35h
   call     far writeHex16          ; 0290h  9Ah [0000h][0000h]

   mov      ax, seg dest_label4     ; 0295h  B8h [0000h]
   mov      dx, 0A3Dh               ; 0298h  BAh 0A3Dh
   call     far writeHex16          ; 029Bh  9Ah [0000h][0000h]

   mov      ax, dest_label4         ; 02A0h  B8h [0274h]
   mov      dx, 0A43h               ; 02A3h  BAh 0A43h
   call     far writeHex16          ; 02A6h  9Ah [0000h][0000h]

   jmp      return_label4           ; 02ABh  E9h FDA3h

exit_label:                         ; 02AEh

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

;############## segmento codice 2 #################

SEGMENT     LIBCODE ALIGN=16 PUBLIC USE16 CLASS=CODE

; destinazione del JMP diretto intersegmento (Ptr16:Ptr16)

dest_label5:                        ; 0000h
   mov      di, strMsg5             ; 0000h  BFh [012Ch]
   mov      dx, 0B00h               ; 0003h  BAh 0B00h
   call     far writeString         ; 0006h  9Ah [0000h][0000h]
   
   mov      ax, seg orig_label5     ; 000Bh  B8h [0000h]
   mov      dx, 0B2Fh               ; 000Eh  BAh 0B2Fh
   call     far writeHex16          ; 0011h  9Ah [0000h][0000h]

   mov      ax, orig_label5         ; 0016h  B8h [0051h]
   mov      dx, 0B35h               ; 0019h  BAh 0B35h
   call     far writeHex16          ; 001Ch  9Ah [0000h][0000h]

   mov      ax, seg dest_label5     ; 0021h  B8h [0000h]
   mov      dx, 0B3Dh               ; 0024h  BAh 0B3Dh
   call     far writeHex16          ; 0027h  9Ah [0000h][0000h]

   mov      ax, dest_label5         ; 002Ch  B8h [0000h]
   mov      dx, 0B43h               ; 002Fh  BAh 0B43h
   call     far writeHex16          ; 0032h  9Ah [0000h][0000h]

   jmp      far return_label5       ; 0037h  EAh [0000h][0056h]

; destinazione del JMP indiretto intersegmento (Mem16:Mem16)

dest_label6:                        ; 003Ch
   mov      di, strMsg6             ; 003Ch  BFh [0170h]
   mov      dx, 0C00h               ; 003Fh  BAh 0C00h
   call     far writeString         ; 0042h  9Ah [0000h][0000h]

   mov      ax, seg orig_label6     ; 0047h  B8h [0000h]
   mov      dx, 0C2Fh               ; 004Ah  BAh 0C2Fh
   call     far writeHex16          ; 004Dh  9Ah [0000h][0000h]

   mov      ax, orig_label6         ; 0052h  B8h [0062h]
   mov      dx, 0C35h               ; 0055h  BAh 0C35h
   call     far writeHex16          ; 0058h  9Ah [h:0000h]

   mov      ax, seg dest_label6     ; 005Dh  B8h [0000h]
   mov      dx, 0C3Dh               ; 0060h  BAh 0C3Dh
   call     far writeHex16          ; 0063h  9Ah [0000h][0000h]

   mov      ax, dest_label6         ; 0068h  B8h [003Ch]
   mov      dx, 0C43h               ; 006Bh  BAh 0C43h
   call     far writeHex16          ; 006Eh  9Ah [0000h][0000h]

   jmp      far return_label6       ; 0073h  EAh [0066h][0000h]

;################# segmento stack #################

SEGMENT     STACKSEGM ALIGN=16 STACK USE16 CLASS=STACK

            resb     STACK_SIZE     ; 1024 byte per lo stack
            
;##################################################