# Output from a debug script showing how INT places values on the stack, # and how it loads CS:IP from the interrupt vector in low memory. # These comments (prefixed by '#') were added to the output file by # hand, to explain what is going on. -IAN! idallen@ncf.ca # First, fill memory with 2000h zeroes, to make things easier to see. # For the same reason, fill some of the stack area with zeroes. -f 0100 l 2000 00 -f ffe0 l 20 00 # Assemble a small program that triggers INT 4h. We calculate that # the new IP will be loaded from address (4*4)=0010 (0000:0010) and # the new CS will be loaded from address (4*4+2)=0012 (0000:0012). # -a 0100 1426:0100 int 4h 1426:0102 # Display some of low memory (segment zero!), showing the first eight # interrupt vectors. (Each vector takes 2+2=4 bytes.) # We see that location 000:0010 contains 0465 and 0000:0012 contains 0070 -d 0000:0000 l 20 0000:0000 9E 01 00 00 00 04 70 00-16 00 6B DE 65 04 70 00 ......p...k.e.p. 0000:0010 65 04 70 00 54 FF 00 F0-08 80 00 F0 6F EF 00 F0 e.p.T.......o... # Display our starting registers and the stack area before the INT. # Note that this INT is a 2-byte instruction (bit pattern CD04). -r AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1426 ES=1426 SS=1426 CS=1426 IP=0100 NV UP EI PL NZ NA PO NC 1426:0100 CD04 INT 04 -d ffe0 l 20 1426:FFE0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 1426:FFF0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ # Trace the INT. Note how the CS, IP, SP, and stack memory all change. # The IP is incremented by 2 bytes (the size of INT 4) from 0100 to 0102. # The first item PUSHed by the INT is 2 bytes of Flags: F202 # Next pushed is the old CS (1426) followed by the incremented IP (0102). # The IP is loaded with the value from 0000:0010 # The CS is loaded with the value from 0000:0012 -t AX=0000 BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000 DS=1426 ES=1426 SS=1426 CS=0070 IP=0465 NV UP DI PL NZ NA PO NC 0070:0465 CF IRET -d ffe0 l 20 1426:FFE0 00 00 00 00 00 00 00 00-02 01 26 14 02 F2 00 00 ..........&..... 1426:FFF0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ # We see six bytes pushed on the stack - the SP went from FFEE to FFE8. # We are now about to execute code at CS:IP = 0070:0465, inside the # interrupt service routine for "INT 4h". Looking at the first # instruction of this routine (above), we see it is an immediate "return # from interrupt" - IRET - this particular service routine does nothing! # When the service routine does a "return from interrupt", the CS:IP and # Flags will all be restored, and we will be back in segment 1426 at # address 0102. Let's do the trace of the IRET instruction: -t AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1426 ES=1426 SS=1426 CS=1426 IP=0102 NV UP EI PL NZ NA PO NC 1426:0102 0000 ADD [BX+SI],AL DS:0000=CD # As expected, the IRET reloaded the flags, the CS, and the IP. # We are back in our original code segement, right after the INT instruction. # "Real" interrupt service routines do many things before returning. # All done! -q