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.
PearOs wrote:DS (Data Segment) how will I find the value for this? Or will the Video Bios not care?
If it's not a parameter for the function you're calling, then the video BIOS won't care.
Oh ok cool. Now at the moment I don't change CS on calls or any jump instruction. Should you? If so what do you set cs to? Is it a formula using the new offset?
Ok so when I was debugging I ran into a really interesting thing that I never have seen before, it makes sense but I am wondering how many Opcodes this will affect as I do not have this implemented.
Take this Instruction for example
Add ax, byte 255
This will when ran subtract 1 from ax because 255 as a byte is -1.
Add ax, short 65535
Will do the same thing as above, minus 1 from ax.
Does this apply to all Math instructions? Where if whatever operand you have whether its a short or byte it will convert it to a negative first? I ask this because I handle everything as Ushorts and Bytes so if I do
Value in AX + Ushort NegativeOperand It will add, so I write code to check for negatives and then it fixes this.
When both operands are the same size, it doesn't matter if you handle them as signed or unsigned (at least for addition, subtraction, and multiplication). If your emulator is written in C, you should use unsigned integers for those operations: integer overflow is undefined for signed integers, and assembly language relies a surprising amount on overflowing integers.
For the exact behavior of individual instructions, you should probably refer to Intel's manuals. However, I did find this document, which says immediate operands are sign-extended for the add instruction. Once you sign-extend the value, you can perform unsigned addition and the result will be correct even for "negative" numbers.
Octocontrabass wrote:When both operands are the same size, it doesn't matter if you handle them as signed or unsigned (at least for addition, subtraction, and multiplication). If your emulator is written in C, you should use unsigned integers for those operations: integer overflow is undefined for signed integers, and assembly language relies a surprising amount on overflowing integers.
For the exact behavior of individual instructions, you should probably refer to Intel's manuals. However, I did find this document, which says immediate operands are sign-extended for the add instruction. Once you sign-extend the value, you can perform unsigned addition and the result will be correct even for "negative" numbers.
Oh ok. Well I fixed that bug and a few others but what is the best way to test out my 8086 emulator without having to check each and every single line against bochs emulation of the same opcodes? Like I have two bochs open, one in real mode running int10 and I am stepping through each instruction and one with my Os stepping through each instruction its running. Is there a better way to test my emulator to make sure everything is working correctly? Thanks guys, Matt
You could make a trace log using a working emulator (like Bochs, although I don't know if it's the best choice for this) and have your emulator also produce a log. When the logs differ, that means there's a bug in your emulator.
You may want to build your emulator as a separate program until you're sure it works properly, rather than trying to debug it while it messes with the (emulated) video card.
Octocontrabass wrote:You could make a trace log using a working emulator (like Bochs, although I don't know if it's the best choice for this) and have your emulator also produce a log. When the logs differ, that means there's a bug in your emulator.
You may want to build your emulator as a separate program until you're sure it works properly, rather than trying to debug it while it messes with the (emulated) video card.
Ok thanks for the reply. I think ill try writing a debugging program that will run bochs emulation for setting the mode via real mode and my OS running in bochs using com ports and do it that way. Definetley will be faster than checking each instruction and has less human error then
Ok I have almost got my emulator 100% working I just have this one instruction to implement and I don't know how. I have an idea but I figured I would ask here.
LEA is a weird instruction. Rather than loading a value from an offset, it loads the offset. This makes it useful for doing address calculations, but it's also a really quick way to do math without changing any flags. The following two sections of code are equivalent (assuming there's enough stack space for pushf/popf):
Octocontrabass wrote:LEA is a weird instruction. Rather than loading a value from an offset, it loads the offset. This makes it useful for doing address calculations, but it's also a really quick way to do math without changing any flags. The following two sections of code are equivalent (assuming there's enough stack space for pushf/popf):
Also, note that byte offsets following mod r/m bytes are signed. "Byte 0xFE" is equivalent to "word 0xFFFE".
Ok thank you! I noticed something strange, I got my emulator to set a video mode but after setting one, its sets another one, different from the one I wanted and then sets the one I wanted again and then makes the screen go weird and eventually crashes the Bios. So I think I have a bug somewhere I guess ill see if my debugger can track it down.
Octocontrabass wrote:How does your emulator know when the BIOS code is done?
When it reachs a iret instruction. Which is the same way Bochs does it. At the moment I can tell when its bugged out because I have Bochs logging Serial Port 1 to a file and my Os is printing out everything it runs to that file so I can tell register changes, and what Opcodes its running. Kinda neat.
(I would put values on the emulated stack to make it look like the return address is 0xFFFF:0x0000, and then end emulation when it attempts to jump to that address.)
(I would put values on the emulated stack to make it look like the return address is 0xFFFF:0x0000, and then end emulation when it attempts to jump to that address.)
Ok, yeah I already put values on the stack but I noticed VMWare first thing it tried to do was run a Interrupt which is weird. I rewrote the code and made it faster so I'm gonna see if It finally sets video modes with no problem or what its doing.
Thanks, Matt
Edit: Well in Bochs I let Bochs run until it hits "CLD" which is close to the end of the Video Set Mode Code. My emulator runs 100% fine up to CLD it just sets two video modes and I have no idea why. I ran the debugger and it shows that all the instructions between Bochs and what my Emulator did are the same yet it still sets two modes. I wonder if my OUT instruction is setting the wrong address or value or something.