Page 2 of 3

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 8:37 pm
by SpyderTL
Try running your OS in BOCHS in debug mode, and stepping through your code. It's almost impossible to troubleshoot GDT/IDT problems without it.

And BASICFreak is right about not needing CLI and STI in your interrupt handler. The CPU will do that for you.

Also, not all interrupts will push an error code to the stack. In fact, most of them don't. The wiki link I posted above has a list.

I'd almost recommend not using someone else's code. You are better off reading someone's code to see how they solved certain problems, and then considering that when you write your own code. Their code may be wrong, or it may rely heavily on other code that they wrote that you haven't seen.

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 9:21 pm
by chris13524
I tried just looking around, but nothing seemed to work, that is why I resorted to copying. That is a thought though, maybe it doesn't work? I would assume that it works though as it was a release.
You are destroying your stack!
You pop error code and int number, but never push them
Where am I poping anything? I do popa at the bottom of my handler, but only after I pusha.

My friend:
I think I got QEMU to dump the actual faults heres the log.
I've attached the log he sent me. Anything you guys can make of that? You guys obviously got more experience than me :D

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 9:31 pm
by BASICFreak
chris13524 wrote:
You are destroying your stack!
You pop error code and int number, but never push them
Where am I poping anything? I do popa at the bottom of my handler, but only after I pusha.
You don't actually use pop, but you add to ESP (Which a pop would also do)

Code: Select all

add %esp, 8 #Removes data from ISR (error code and INT number)
You have never pushed/stored the INT number, and only a few exceptions push error codes.

So you have effectively removed 2 DWORDS from your return address which is 3 DWORDS for IRET (Addr, CS, EFLAGS - I don't recall the actual order)



Best Regards,

B!

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 9:34 pm
by chris13524
Ah, that makes sense. That still doesn't explain why a hlt in the beginning of my handler doesn't halt the OS and prevent faulty code from running.

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 9:41 pm
by chris13524
One thing, when converting from the CakeOS assembler syntax to GNU syntax, there were a few issues that I'm not sure about:

Code: Select all

mov eax, [esp+4]  ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax]        ; Load the new GDT pointer
was translated by me to

Code: Select all

mov %eax, (%esp,4)  # Get the pointer to the GDT, passed as a parameter.
lgdt (%eax)        # Load the new GDT pointer
This however causes a "qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a0000" error in my console and crashes QEMU (which it hasn't done before). In addition, the "mov" line has the warning: "scale factor of 4 without an index register" I tried to fix this by changing it to:

Code: Select all

#mov %eax, (%esp,4)  # Get the pointer to the GDT, passed as a parameter.
lgdt (%eax,4)        # Load the new GDT pointer
which fixed the fatal error, but the warning is now on the "lgdt" line.

Also, another line while setting up the GDT, you have to do a far jump, I took from the wiki and CakeOS this:

Code: Select all

jmp 0x08:.flush   ; 0x08 is the offset to our code segment: Far jump!
.flush:
Which doesn't work in GNU: "junk `:.flush' after expression"

No idea if this is right, but I tried:

Code: Select all

jmp .flush   # 0x08 is the offset to our code segment: Far jump!
.skip 0x08
.flush:

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 10:02 pm
by BASICFreak
chris13524 wrote:One thing, when converting from the CakeOS assembler syntax to GNU syntax, there were a few issues that I'm not sure about:

Code: Select all

mov eax, [esp+4]  ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax]        ; Load the new GDT pointer
was translated by me to

Code: Select all

mov %eax, (%esp,4)  # Get the pointer to the GDT, passed as a parameter.
lgdt (%eax)        # Load the new GDT pointer
I don't myself use GAS, but I do know the SRC, DEST is backwards you should "mov (%esp,4), %eax"
This however causes a "qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a0000" error in my console and crashes QEMU (which it hasn't done before). In addition, the "mov" line has the warning: "scale factor of 4 without an index register" I tried to fix this by changing it to:

Code: Select all

#mov %eax, (%esp,4)  # Get the pointer to the GDT, passed as a parameter.
lgdt (%eax,4)        # Load the new GDT pointer
which fixed the fatal error, but the warning is now on the "lgdt" line.
So you never actually loaded your GDT Address...
Also, another line while setting up the GDT, you have to do a far jump, I took from the wiki and CakeOS this:

Code: Select all

jmp 0x08:.flush   ; 0x08 is the offset to our code segment: Far jump!
.flush:
Which doesn't work in GNU: "junk `:.flush' after expression"

No idea if this is right, but I tried:

Code: Select all

jmp .flush   # 0x08 is the offset to our code segment: Far jump!
.skip 0x08
.flush:
Again you haven't loaded your GDT. All those segments are invalid, so you get a #GP and fail to handle that, get a #DF, fail to handle that - then finally the CPU resets with a #TF.


EDIT: You should learn the language you are using.

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 10:20 pm
by chris13524
How should I correctly load my GDT?

My updated gdt_flush function:

Code: Select all

.global gdt_flush
gdt_flush:
    movl 4(%esp), %eax  # Get the pointer to the GDT, passed as a parameter.
    lgdt (%esp)        # Load the new GDT pointer

    mov %ax, 0x10      # 0x10 is the offset in the GDT to our data segment
    mov %ds, %ax        # Load all data segment selectors
    mov %es, %ax
    mov %fs, %ax
    mov %gs, %ax
    mov %ss, %ax

    jmp $0x08, $flush   # 0x08 is the offset to our code segment: Far jump!

flush:
    ret
Edit: Yes, I know I should do that, I just fear that it would take a ton of my time up learning stuff that isn't OS-type asm. Know what I mean? This is sort of a learning experience writing an OS to also learn ASM and C.

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 10:27 pm
by BASICFreak
chris13524 wrote:How should I correctly load my GDT?

My updated gdt_flush function:

Code: Select all

.global gdt_flush
gdt_flush:
    movl 4(%esp), %eax  # Get the pointer to the GDT, passed as a parameter.
    lgdt (%esp)        # Load the new GDT pointer

    mov %ax, 0x10      # 0x10 is the offset in the GDT to our data segment
    mov %ds, %ax        # Load all data segment selectors
    mov %es, %ax
    mov %fs, %ax
    mov %gs, %ax
    mov %ss, %ax

    jmp $0x08, $flush   # 0x08 is the offset to our code segment: Far jump!

flush:
    ret
If you were using intel syntax you might be right... all those moves are backwards and IDK about GAS but its a jmp 0x8:flush in intel (maybe jmp 0x08:$flush in GAS)

I'm also unsure what mov %ax, 0x10 will do, as in GAS IINM that states move register ax to 0x10

you should move 0x10 into ax
then you should move ax into the segment registers, not from seg regs to ax

OR at the very lest, if you are going to "borrow" (steal) other's codes you might as well use NASM to assemble their code... And not try to convert syntaxs you don't know.

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 10:46 pm
by chris13524
Ah, that could be an issue. I fixed that and pushed my updated version..still doesn't work :/ lol

I swear, it's probably like a tiny one liner somewhere I'm missing.

Re: Problem writing interrupts handler?

Posted: Mon Feb 29, 2016 11:08 pm
by BASICFreak
Never seen the push go up.

BUT these will help you, it is very difficult to find GAS examples...

http://www.superfrink.net/athenaeum/OS- ... q-isr.html
It is a Clock ISR, but study the code - learn what order things go in and what they do.

http://forum.osdev.org/viewtopic.php?f= ... 94&start=0
That is a GAS GDT flush.

AGAIN - STUDY THE CODE - DON'T C&P!

I'm off for the night.



Best regards,

B!

Re: Problem writing interrupts handler?

Posted: Tue Mar 01, 2016 5:50 am
by chris13524
Hmm, correct me if I'm wrong, but shouldn't putting a hlt at the top of my interrupt function (asm) stop the system? Can I ignore potential problems in my handler until I can get that halt to happen?

I've updated my GDT code and it still doesn't work :(

I noticed in one of those links you just sent me about an incorrect pointer?

Code: Select all

(gdt_entry**) 
But it seems that they were disregarding that issue.

Re: Problem writing interrupts handler?

Posted: Tue Mar 01, 2016 9:38 am
by iansjack
chris13524 wrote:Hmm, correct me if I'm wrong, but shouldn't putting a hlt at the top of my interrupt function (asm) stop the system?
Not necessarily. The system will only wait until the next interrupt is received if interrupts are enabled. Whether this is the case in your interrupt routine depends upon whether it was called via an interrupt gate or a trap gate; or you could insert an instruction to disable interrupts before the "hlt" instruction. And, of course, the "hlt" will only take effect if you actually enter the interrupt routine; this depends upon your IDT being correct in the first place.

You should probably use a debugger to inspect the IDT to verify that it is correct.

Re: Problem writing interrupts handler?

Posted: Tue Mar 01, 2016 9:56 am
by chris13524
Yeah ok, I added "cli hlt" to the top of my handler. Doesn't halt the system so the only other possible thing would be my IDT (or GDT). How much would incorrectly setting up the GDT effect the IDT (I expect greatly)?

I took the nuclear approach and copied all of the interrupt handler from CakeOS to my OS and it doesn't work. Seems like CakeOS doesn't work after all, or maybe it's an emulator thing. I'll see what other OSs are out there that I could take a look at.

How would I use a debugger for this? Eclipse appears to be able to step through the compiled assembly code and display a **** ton of registers, but that's about it. My friend sort of knows how to use GDB, but I'm not sure if he really knows what he's doing. What should I be looking for?

Re: Problem writing interrupts handler?

Posted: Tue Mar 01, 2016 10:42 am
by SpyderTL
Traditionally, you would run your application, and then run a debugger that would watch your application. But in this situation, it's not as simple, since your application is actually an operating system.

So, what you can do is run your operating system in an emulator, like Bochs, that has a built-in debugger.

Download Bochs, and run bochsdbg.exe, and set it up to use your boot disk image as the first floppy drive. (Be sure to save your settings, or else you'll have to set this up every time...)

Then when you run the emulator, it will automatically break on the first instruction of your boot loader. You can use the Bochs console to add a break point (if you happen to know where in memory your code lives) by typing "b 0x1000" (to automatically break at linear address 0x1000) and hitting enter, and then type "c" and hit enter to continue running your OS. Once you hit the breakpoint, you can type "r" to view all of the CPU register values and make sure they make sense. You can also type "s" to step through your OS one instruction at a time.

It takes a little while to get used to, but it's almost impossible to write an OS without it.

Re: Problem writing interrupts handler?

Posted: Tue Mar 01, 2016 11:11 am
by iansjack
You can also use gdb in conjunction with qemu, which is a great setup for debugging C source. For pure assembler debugging my favourite is SimNow. VirtualBox also has a debugger, but it's a bit tricky to use it. I'd agree that learning debugging techniques is an essential for OS development. And it is a great aid in learning how the processor works. a Google search will reveal lots of information about gdb.