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.
hi! i'm new! and by way of introduction, i have a problem that most likely has a simple solution that i just can't see. i'm just going to plop all my stuff down here and hope that the problem jumps out at someone:
problem:
- a far call puts incorrect return address on stack
- corresponding retf returns to wrong address (not even the (wrong) address that the call put on the stack))
[cpu 386]
[org 0x7C00]
[bits 16]
;set new stack values
cli
xor sp,sp
mov ax,0xA000
mov ss,ax
;setup for writing to text buffer
mov ax,0xB800
mov es,ax
xor ax,ax
mov [es:0],word 0x0745
;remap pics (ripped from the wiki)
jmp 0x0000:pic_remap ;this is extraneous
pic_remap:
in al,0x21
shl ax,8
in al,0xA1
push ax
mov al,0x10+0x01
out 0x20,al
push ax
call 0x0:0x7C63 ;!!! RETURN SHOULD COME BACK HERE V (this is the right address, too. i'll post disassembly if you don't believe me
;we never get here, so ignore the rest of this
pop ax
out 0xA0,al
call busy
mov al,0x20
out 0x21,al
call busy
add al,8
out 0xA1,al
call busy
mov al,0x04
out 0x21,al
call busy
mov al,0x02
out 0xA1,al
call busy
mov al,0x01
out 0x21,al
call busy
out 0xA1,al
call busy
pop ax
out 0xA1,al
shr ax,8
out 0x21,al
busy: ;by the way, how busy do i need to make this?
mov ax,0x0741
mov [es:0],word ax
jmp 0x0:0x7C6f
.0:
inc ax
mov [es:0],word ax
jmp 0x0:0x7C79
.1:
inc ax
mov [es:0],word ax ;we get through here fine, but...
retf ;!!! THIS DOESN'T WORK (see bochs output)
hlt
idt:
dw 0x100
dd 0x00000600
gdt:
dw 0x4
dd 0x00000700
times 510-($-$$) db 0
dw 0xaa55 ;this is fine
times 1048576-512 db 0 ;this just makes the image a valid size to be treated as a hard disk
as you can see in the second cpu and stack dump, retf acted like it took the values, but MAGICALLY CHANGED THEM TO 0xffff:0xffff!!! how? why? what did i do?
i had used far calls because it was doing the same thing earlier (returning to never never land), and i was just trying something new.
i don't know what i'm doing wrong. i'm inexperienced with asm and bochs, much more so operating system development. if anyone has a hunch as to what's wrong, and needs more information, let me know!
void wrote:
as you can see in the second cpu and stack dump, retf acted like it took the values, but MAGICALLY CHANGED THEM TO 0xffff:0xffff!!! how? why? what did i do?
That's instant triple-fault-and-reboot. It's a setting in bochs, which makes the computer reboot when your OS makes a horrible error.
First, there's 2 different types of "call" instructions. The first one is a "near call" where the CPU puts IP on the stack. The second one is a "far call" where the CPU puts CS and IP on the stack. There's also 2 different return instructions - one that gets IP from the stack and returns to it (RET) and the other that gets both CS and IP from the stack (RETF). The far call and far return are used for calling code in a different code segment. The near call and near return are used for calling code in the same code segment.
You must make sure that the call and the return match. For example, if you do "call busy" the CPU will only put IP on the stack, then if you do "RETF" the CPU will try to get CS and IP from the stack and crash because CS wasn't put on the stack by the call instruction.
NEVER hard code offsets - it's too hard to maintain the code, too easy to mess it up and very hard for other people to figure out which address is where. That's why assemblers have labels.
Your stack is in video display memory. SS:ESP is set to 0xA0000:0x0000 so the first time you push anything onto the stack SP will wrap around and your stack will be at 0xA0000:0xFFFE. The value in SS won't change (i.e. it won't become 0x9000:0xFFFE or 0x9FFF:0xFFFE). At the moment this doesn't matter because that part of video display memory isn't used in text mode, but it's extremely bad anyway. Also all modern BIOSs use the area below 0xA000:0x0000 for an EBDA (Extended BIOS Data Area), so you don't want your stack just below 0xA0000:00000 either. I wouldn't use anything between 0x00098000 and 0x000FFFFF (unless "INT 0x12" tells you higher addresses are safe).
The code in the "busy" routine is there for dodgy chipsets (mostly 80386 motherboards). No-one really agrees on how dodgy some motherboards are or what the most reliable way of avoiding the "dodgy-ness" is. Possibly the best method is to write to a dummy I/O port that is in the same "ISA" area (a dummy write to a PCI device wouldn't take as long).
The code I've been using to remap the PIC chips has no additional delays at all. Instead I make sure I alternate between the PIC chips - I send data to the slave PIC chip when I need a delay for the master PIC chip, and I send data to the master PIC chip when I need a delay for the slave PIC chip. This is mostly the same delay as writing to a dummy I/O port. AFAIK my code has never failed.
Lastly, what are you going to do when you run out of space in the first sector? 512 bytes isn't a lot. I'm guessing you'll need to load more code from the floppy, but to do this you need to use the BIOS, and the BIOS will need to use the PIC chips. Basically, you can't remap the PIC chips until you don't need the BIOS anymore...
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.
This is "void", but my name was taken on this board, so I'm now Mr. Man (creativity++).
Anyway! Just wanted to thank you guys for the help. The problem was the stack being in video memory - as soon as I moved it to 0x9000, it was fine. And yes, I knew better! Blame it on a short-circuiting brain at 3am...
Thank you both for your help. I didn't know about that setting in bochs, or about the EBDA (seems I might have to move my stack again).
Right now, I'm reading through all the docs on vga, ata/ide, and keyboard controllers. Next step for me is a command interpreter (and tools! edit, asm/disasm, and debuggery utils. Then a file system. Then THE UNIVERSE!).
Mr. Man wrote:Thank you both for your help. I didn't know about that setting in bochs, or about the EBDA (seems I might have to move my stack again).
That's ok. I'm just poking at people when I see something quickly that they missed. The rest of the time I'm just developing my own OS.
Right now, I'm reading through all the docs on vga, ata/ide, and keyboard controllers. Next step for me is a command interpreter (and tools! edit, asm/disasm, and debuggery utils. Then a file system. Then THE UNIVERSE!).
Command line interpreter? A shell? Try ncsh. I designed it to be portable between OSes without a lot of hassle, it should match your OS pretty well and without any trouble - if you support C++.
I'm still looking for a proper editor as well. I think I'm going to port YASM and GCC for compiler stuff, debugger isn't necessary at first. File system is the first thing I need to get working properly.