Interrupt not working properly

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Interrupt not working properly

Post by nitinjavakid »

Code: Select all

;storing previous interrupt address
   mov ax,0
   mov ds,ax
   mov ax,[ds:08h*4]
   mov [previpaddress], ax
   mov ax, [ds:08h*4 + 2]
   mov [prevcsaddress], ax

;putting in new interrupt address
   mov ax,0
   mov ds,ax
   mov word [ds:08h*4], temp
   mov word [ds:08h*4 + 2],0x07c0

temp: 
   cli
   mov ax, 0x07c0
   mov ds, ax
   mov es, ax ; used by int 0x10 13h

   mov ax, 0x00
   mov ss, ax    
   mov sp, 0x9c00 

   push DWORD msg  ; pushing the address of msg
   call _print
   sub sp,2

   push DWORD msg1
   call _print
   sub sp,2
   sti

   
   mov cs,[prevcsaddress]
   jmp [previpaddress]

_print:
   push bp
   mov bp, sp
   mov si, [bp+4]
   mov ah,0x0e
   mov bh,0
   mov cx,1
  loopprint:
   lodsb
   cmp al,00
   je exitprint
   
   int 0x10
   jmp loopprint
  exitprint:
   pop bp
   ret

msg   db 'Welcome to the world of amazing things.',13,10,0
msg1  db 'I feel great pleasure in providing you with nothing',0
prevcsaddress dw 0
previpaddress dw 0
Actually, I want to execute the temp: part again and again continuously. So, I thought interrupt 08h which is a timer interrupt would do it continuously. But this thing is getting executed only twice:( Not continuously. Any suggestions?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Interrupt not working properly

Post by Brendan »

Hi,
nitinjavakid wrote:Actually, I want to execute the temp: part again and again continuously. So, I thought interrupt 08h which is a timer interrupt would do it continuously. But this thing is getting executed only twice:( Not continuously. Any suggestions?
To be honest, I'm surprised it worked at all - your IRQ handler trashes registers in use by anything it interrupts. It also looks like you're getting your segments mixed up, assuming DS is normally equal to CS (DS can't be 0x0000 and 0x7C00 at the same time), which it should be unless you're using a really messed up linker script.

When the IRQ handler calls "print" it pushes 4 bytes and then pops 2 bytes. There's also no need to disable and then re-enable IRQs (the CPU does this automatically anyway).

The IRQ handler can't assume that the direction flag is set or cleared, so instructions like "lodsb" might go backwards (decrement SI instead of incrementing it). The code for "print" doesn't need a stack frame either, and it's a waste of time pushing it's arguments on the stack. I also like to write functions (like print) so they don't trash registers either - it makes it much easier to maintain the code.

Lastly, I have no idea how the assembler allowed something like "mov cs,[prevcsaddress]" to assemble.

Code: Select all

;storing previous interrupt address
   mov ax,0
   mov ds,ax
   mov ax,[ds:08h*4]
   mov [cs:prevaddress], ax
   mov ax, [ds:08h*4 + 2]
   mov [cs:prevaddress + 2], ax

;putting in new interrupt address
;   mov ax,0        <- not needed
;   mov ds,ax       <- not needed
   mov word [ds:08h*4], temp
   mov word [ds:08h*4 + 2],0x07c0

Code: Select all

;IRQ handler

temp: 
   push si

   mov si,msg
   call _print

   mov si,msg1
   call _print

   pop si
   jmp far [cs:prevaddress]

;Print the string at CS:SI

_print:
   pusha
   cld  ; <- needed for "lodsb"
   mov ah,0x0e
   mov bh,0
  loopprint:
   cs lodsb    ;Use CS segment override to avoid messing with segment registers
   cmp al,00
   je exitprint
   int 0x10
   jmp loopprint
  exitprint:
   popa
   ret

msg   db 'Welcome to the world of amazing things.',13,10,0
msg1  db 'I feel great pleasure in providing you with nothing',0
prevaddress dw 0,0
BTW I'd recommend using CS = DS = 0, and then putting "org 0x7C00" at the start of your boot loader (it makes things easier to figure out).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

But the code still doesnt work. I tried the new one. It still shows the message only one time. :(

Can gs be used while jumping?
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

come people! plzzzz help me! I am a complete newbie to os development.


Well actually a newbie to assembly as well :?
User avatar
B.E
Member
Member
Posts: 275
Joined: Sat Oct 21, 2006 5:29 pm
Location: Brisbane Australia
Contact:

Post by B.E »

I think you should ether use GRUB and skip the boot loader part, or learn assembly(ie. tackle little things before tackling a giant).

One thing to note if temp is a ISR, then i should return with a iret not a just a ret
Image
Microsoft: "let everyone run after us. We'll just INNOV~1"
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,
B.E wrote:One thing to note if temp is a ISR, then i should return with a iret not a just a ret
For "interrupt chaining" in real mode, the new IRQ handler jumps to the old IRQ hander in a way that the old IRQ still runs, and doesn't know the difference - that's why there's no EOI and no IRET...

@nitinjavakid: I can't see anything wrong that I didn't mention previously - is it possible to see all of your source?


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

Code: Select all

;storing previous interrupt address
   mov ax,0
   mov ds,ax
   
   mov word ax,[ds:08h*4]
   mov word [previpaddress], ax
   mov word ax, [ds:08h*4 + 2]
   mov word [prevcsaddress], ax
   
;putting in new interrupt address
   mov word [ds:08h*4], temp
   mov word [ds:08h*4 + 2],0x07c0
   
temp: 
   cli
   mov ax, 0x07c0
   mov ds, ax
   mov es, ax ; used by int 0x10 13h

   mov ax, 0x00
   mov ss, ax    
   mov sp, 0x9F00 
   push si
   mov si, msg  ; pushing the address of msg
   call _print

  
   mov si,msg1
   call _print
   pop si
   sti

   mov word gs,[prevcsaddress]
   jmp far [gs:previpaddress]
   
_print:
   pusha
   cld
   mov ah,0x0e
   mov bh,0
   mov cx,1
  loopprint:
   lodsb
   cmp al,00
   je exitprint
   
   int 0x10
   jmp loopprint
  exitprint:
   popa
   ret

msg   db 'Welcome to the world of amazing things.',13,10,0
msg1   db 'Damn',13,10,0
prevcsaddress dw 0
previpaddress dw 0
This is all i have written. Is there any limitations of es,gs,fs etc. I mean why cant they be used for indirect addressing in jmp instruction. :(
I think you should ether use GRUB and skip the boot loader part, or learn assembly(ie. tackle little things before tackling a giant).
Please name a good book on assembly using NASM.
Last edited by nitinjavakid on Sun Nov 05, 2006 9:36 am, edited 1 time in total.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

First you need to disable ints, like this, from MiniDOS and try "CS" instead of 0x07c0.

Code: Select all

Installints:
        push  ds                            ; Save DS
        cli                                 ; Turn off int's
        xor   ax,ax
        mov   ds,ax			    ; 0 DS
        mov   word [ds:20h*4],int20	    ; load int vecter with int20h address
        mov   word [ds:20h*4+2],cs          ; + CS

        mov   word [ds:21h*4],int21	    ; load int vecter with int21h address
        mov   word [ds:21h*4+2],cs          ; + CS
        sti                                 ; Turn on int's
        pop   ds                            ; restore DS
	     ret                                 ; Return
Also do not go to old timer, why are you saving old address when your rebooting.
Uses "iret" at end of your function.
Put this at end of function

Code: Select all

	mov al, 0x20
	out 0x20,al ; quiet screaming irq chip.
you should not use theres "cli" or "sti" in IRQ function as thats whats this, is for iret.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,

You need to tell the assembler where in memory your code starts and initialise a stack at the start of your code (NOT within the IRQ handler, which should use the interrupted code's stack).

You also need to give the CPU something to do in-between IRQs. The CLI/STI is still not needed.

It may have been a good idea to re-read my last post - your new code makes most of the mistakes I mentioned earlier (like not saving/restoring registers used by the IRQ handler).

Code: Select all

    org 0x7C00

    xor ax,ax
    mov ds,ax
    cli
    mov ss,ax
    mov sp,stackTop
    sti

;storing previous interrupt address
   
   mov word ax,[08h*4]
   mov word [prevaddress], ax
   mov word ax, [08h*4 + 2]
   mov word [prevaddress+2], ax
   
;putting in new interrupt address
   cli                      ; <- Dex was right about this!
   mov word [08h*4], temp
   mov word [08h*4 + 2],0
   sti

;Lock up (nothing else to do while waiting for IRQs).

    jmp $


;IRQ handler

temp:
   push si

   mov si,msg
   call _print

   mov si,msg1
   call _print

   pop si
   jmp far [cs:prevaddress]


;Print the string at CS:SI

_print:
   pusha
   cld  ; <- needed for "lodsb"
   mov ah,0x0e
   mov bh,0
  loopprint:
   cs lodsb    ;Use CS segment override to avoid messing with segment registers
   cmp al,00
   je exitprint
   int 0x10
   jmp loopprint
  exitprint:
   popa
   ret

    section .data
msg   db 'Welcome to the world of amazing things.',13,10,0
msg1   db 'Damn',13,10,0
    align 4
    section .bss
prevaddress   resd 1
stack:      resb 1024       ;1 KB stack space
stackTop:
    section .text
This is all i have written. Is there any limitations of es,gs,fs etc. I mean why cant they be used for indirect addressing in jmp instruction. :(
First, any register you use in the IRQ handler must be saved and restored, but you can't restore anything after the jump.

Secondly, "jmp far [gs:previpaddress]" will load CS:IP from the 2 words at [gs:previpaddress], it will not load CS with GS.

I'm also a little worried what you're intent is - using video functions within any IRQ handler is a bad idea.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

Splendid! Nice explaination. Also, one more thing,

mov ss,ax

in this statement, can ss be initialized to stack: ? If yes, what will be the effect on the overall program? Damn I have many doubts in my mind. Hope you dont mind it.

Regards,
Nitin
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post by JAAman »

you must always initialize the stack first, rather than leave it at an unknown location:

the combination of:
mov SS, [reg16/32]
mov SP, [imm16/reg16]

will define where in memory your stack is located, and where 'push', 'pop', 'call', and interupts get/put the information, it is important that you place the stack out of the way where it will not overwrite anything, nor be overwritten by anything

remember the stack grows downwards (and is decremented before write) , so within the SS segment, SP should be initialized to the address 1 higher than the highest address you want it to use)
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

Splendid! Great Help!

This forum rocks!!! :)
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

Secondly, "jmp far [gs:previpaddress]" will load CS:IP from the 2 words at [gs:previpaddress], it will not load CS with GS.
So, suppose if we have address of a segment stored in some register say fs and the offset stored in another register say bx, then how can we jump to that particular location?

The JMP r/m forms execute a near jump (within the same segment), loading the destination address out of memory or out of a register. The keyword NEAR may be specified, for clarity, in these forms, but is not necessary. Again, operand size can be overridden using JMP WORD mem or JMP DWORD mem.
This is what the nasm manual tells. So I guess through register only jump within the present segment can be done? Am I right?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,
nitinjavakid wrote:
Secondly, "jmp far [gs:previpaddress]" will load CS:IP from the 2 words at [gs:previpaddress], it will not load CS with GS.
So, suppose if we have address of a segment stored in some register say fs and the offset stored in another register say bx, then how can we jump to that particular location?
Basically, CS and IP must be loaded at the same time - otherwise you end up executing code at the new CS and old IP (or at the old CS and the new IP).

To do this you need to have the new CS and IP at the same place. This means either storing them in memory somewhere and doing a "jmp far [indirect]" or pushing them on the stack and doing a "retf".
nitinjavakid wrote:
The JMP r/m forms execute a near jump (within the same segment), loading the destination address out of memory or out of a register. The keyword NEAR may be specified, for clarity, in these forms, but is not necessary. Again, operand size can be overridden using JMP WORD mem or JMP DWORD mem.
This is what the nasm manual tells. So I guess through register only jump within the present segment can be done? Am I right?
Yes.

For your purposes (jumping to a previous IRQ handler) using any register won't work anyway, because you need to restore all registers to how they were before your IRQ handler started before doing the jump.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
nitinjavakid
Member
Member
Posts: 65
Joined: Sat Oct 21, 2006 11:28 am
Location: Exams over!
Contact:

Post by nitinjavakid »

Thanks again!
Post Reply