Working with Real Mode IVT to work on a 8086 Emulator

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
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Working with Real Mode IVT to work on a 8086 Emulator

Post by PearOs »

Hey guys! So I have been working on my 8086 emulator in my operating system finally! Now that I have enough done where I can do so. But I've run into a slight problem. I read the 0x10 Entry in the IVT like this:

Code: Select all

short segment = Memory.Get_16(0x0040);
short offset = Memory.Get_16(0x0040 + 2);
That code above looks right. According to the wiki Interrupt_Vector_Table
Then I tried to convert the segment and offset to a actual Memory address like this:

Code: Select all

INT10Pointer = (uint)((segment * 0x10) + offset);
Which according to this wikie Segmentation thats right. But when I run my Os, I get a physical address of 35745760 which is the 35mb mark and My os doesn't even reach that at the moment. None of my code overwrites the IVT but I wonder if my boot loader might. Hard to say but are my equations right?

Thanks, Matt
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by PearOs »

Ok so I found a bug in my Memory_Get_16 code and fixed that. But then I found a bug within my Segment converter code so the new is:

Code: Select all

short offset = Memory.Get_16(0x0040);
short segment = Memory.Get_16(0x0040 + 2);
INT10Pointer = (uint)((segment * 0x10) + offset);
Which I think is right, and my Os outputs 789246 as the pointer to where INT 10h starts in Memory. So I think that is right.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by b.zaar »

PearOs wrote:

Code: Select all

short segment = Memory.Get_16(0x0040);
short offset = Memory.Get_16(0x0040 + 2);
These are the wrong way round.
PearOs wrote:

Code: Select all

INT10Pointer = (uint)((segment * 0x10) + offset);
And these should be uint16_t before the addition, the max value should be 0xFFFFF = 1048575
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by PearOs »

Ok I see. Well I think I have it right now. Because the offset is first which is 2 bytes then follows the segment which is 2 bytes. Though I have found a very strange bug and I am wondering what you guys think. I have been testing my os's ability
to decompile real mode instructions for the int 10h call. I found a weird one.

lock mov al, byte[si + 61440] which I think is correct.

But when I use nasm disam for the same bytes I get

lock mov al,[si-0x1000] and 0x1000 is (61440) so thats good but why is it minus now? Cause if I write that
instruction in Nasm and decompile it, it will say that "+ 61440" is "- 61440" when thats not what I typed. But if I do "- 61440" I get "+ 61440" from Nasm Dism, did I just find a bug?

Thanks,

Matt
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by Combuster »

PearOs wrote:lock mov al, byte[si + 61440] which I think is correct.
LOCK makes read-modify-write operations atomic across the bus. This is simply a read, and therefore LOCK is invalid.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by Brendan »

Hi,
PearOs wrote:lock mov al,[si-0x1000] and 0x1000 is (61440) so thats good but why is it minus now? Cause if I write that
instruction in Nasm and decompile it, it will say that "+ 61440" is "- 61440" when thats not what I typed. But if I do "- 61440" I get "+ 61440" from Nasm Dism, did I just find a bug?
Note that -4096 (as a signed 16-bit number) is the exact same pattern of bits as 61440 (as an unsigned 16-bit number).

I'm not sure if this is a bug or correct behaviour.

If you assume that the displacement is a signed 16-bit value, then it'd only be capable of storing values from -32768 to +32767 and "[si+61440]" should be treated as a programming error (number too large for signed 16-bit).

If you assume that the displacement is an unsigned 16-bit value (where the CPU ignores overflow and essentially does "offset = (si + unsigned_displacement) & 0xFFFF") then it's not a bug at all.

If you assume that either case is equally valid (e.g. the programmer is free to treat the displacement as signed or unsigned), then that means valid values for the displacement would range from -32768 to 65535.

I tested NASM, and it does accept any value from -32768 to 65536 (inclusive), and gives a "data exceeds bounds" warning for anything outside that range. I don't know why 65536 is allowed (it doesn't fit in any signed or unsigned 16-bit integer).

For debuggers, it's impossible to guess what the original programmer's intent was, and a debugger can't know if it should display "-0x1000" or "+0xF000". Any debugger that displays "-0xF000" is buggy, but I tested ndisasm and it doesn't do that (it displays "-0x1000").


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.
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by PearOs »

Brendan wrote:Hi,
PearOs wrote:lock mov al,[si-0x1000] and 0x1000 is (61440) so thats good but why is it minus now? Cause if I write that
instruction in Nasm and decompile it, it will say that "+ 61440" is "- 61440" when thats not what I typed. But if I do "- 61440" I get "+ 61440" from Nasm Dism, did I just find a bug?
Note that -4096 (as a signed 16-bit number) is the exact same pattern of bits as 61440 (as an unsigned 16-bit number).

I'm not sure if this is a bug or correct behaviour.

If you assume that the displacement is a signed 16-bit value, then it'd only be capable of storing values from -32768 to +32767 and "[si+61440]" should be treated as a programming error (number too large for signed 16-bit).

If you assume that the displacement is an unsigned 16-bit value (where the CPU ignores overflow and essentially does "offset = (si + unsigned_displacement) & 0xFFFF") then it's not a bug at all.

If you assume that either case is equally valid (e.g. the programmer is free to treat the displacement as signed or unsigned), then that means valid values for the displacement would range from -32768 to 65535.

I tested NASM, and it does accept any value from -32768 to 65536 (inclusive), and gives a "data exceeds bounds" warning for anything outside that range. I don't know why 65536 is allowed (it doesn't fit in any signed or unsigned 16-bit integer).

For debuggers, it's impossible to guess what the original programmer's intent was, and a debugger can't know if it should display "-0x1000" or "+0xF000". Any debugger that displays "-0xF000" is buggy, but I tested ndisasm and it doesn't do that (it displays "-0x1000").


Cheers,

Brendan
Ok thanks Brendan! It might be that I am actually not reading back the INT10h code I think because when I look at the opcodes my decompiler is printing out, they don't logically make any sense. I'll attach a pic, also is there anyway I could in Bochs or some other Virtual Machine see what the INT10h code is that they are running? Like I know they load a VESA and VGA Bios so it would be nice to see the original code and then make sure my OS is reading it back properly if you get what I'm saying.

Anyways, here's a few opcodes I'm getting from where INT10h is supposed to be in RAM.
Attachments
Testing 8086 Emulator. The numbers infront of the Opcode are the bytes it read for the opcode and Ignore the [ 0] its just that operand had a 0 value with a displacement.
Testing 8086 Emulator. The numbers infront of the Opcode are the bytes it read for the opcode and Ignore the [ 0] its just that operand had a 0 value with a displacement.
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by PearOs »

So I did some testing on my own and in Bochs I'm getting the exact same instructions that I got in VMWare which leads me to assume I must be overwriting the code somehow. So I the physical address of INT10h and Bochs and found it to be 786762 which is the same one my OS prints out when it runs, which means I'm not overwriting the IVT.

I set a physical address break point in Bochs in real mode and called 786762 and saw the first instruction to be: Pushf which that actually makes some sense. I am using ISOLinux to boot my os but is that somehow overwriting the BIOS code? Cause My code in my OS doesn't.. Thanks a ton.

- Matt
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: Working with Real Mode IVT to work on a 8086 Emulator

Post by PearOs »

Nevermind! I got it! Silly me. I forgot to set my pointer address in my Opcode reader stream. Lol so I was reading code from 0x0. It's working perfectly now. Thanks anyways guys. Ill post back again if I have any further issues. :lol:
Post Reply