OSDev.org https://forum.osdev.org/ |
|
an 8086 PC emulator https://forum.osdev.org/viewtopic.php?f=13&t=23739 |
Page 2 of 2 |
Author: | miker00lz [ Fri Jun 17, 2011 1:12 pm ] |
Post subject: | Re: an 8086 PC emulator |
thepowersgang wrote: If you could provide that test program, that would be lovely. I hope to have this running DOS sometime soon here's the code. what it does is exercise the CPU's EA calculation with a ton of different values in every addressing mode, then compare what it came up with against calculating the same using the ADD instruction. Code: ; testea.asm - A program to test the Intel 8086 CPU's ; various addressing mode calculations. Designed to ; verify correct functionality of my 8086 PC emulator, Fake86. org 100h ;cli push cs pop ds mov si, offset banner call printmsg ;call printmsg mov ax, 0F000h mov es, ax jmp loopmain disptest dw 1234h loopmain: mov cx, oper1 add cx, oper2 mov bx, oper1 mov si, oper2 lea ax, [bx+si] cmp ax, cx jz bxdi mov si, offset strfailbxsi call printmsg bxdi: mov bx, oper1 mov di, oper2 lea ax, [bx+di] cmp ax, cx jz bpsi mov si, offset strfailbxdi call printmsg bpsi: mov bp, oper1 mov si, oper2 lea ax, [bp+si] cmp ax, cx jz bpdi mov si, offset strfailbpsi call printmsg bpdi: mov bp, oper1 mov di, oper2 lea ax, [bp+di] cmp ax, cx jz testsi mov si, offset strfailbpdi call printmsg testsi: mov si, oper1 lea ax, [si] cmp ax, oper1 jz testdi mov si, offset strfailsi call printmsg testdi: mov di, oper1 lea ax, [di] cmp ax, oper1 jz testbx mov si, offset strfaildi call printmsg testbx: mov bx, oper1 lea ax, [bx] cmp ax, oper1 jz disp16 mov si, offset strfailbx call printmsg disp16: mov bx, oper1 lea ax, [bx+8000h] add bx, 8000h cmp ax, bx jz disp8 mov si, offset strfaildisp16 call printmsg disp8: mov bx, oper1 db 8Dh, 01000111b, 80h ;lea ax, [bx+80h] add bx, 0FF80h cmp ax, bx jz nexttest mov si, offset strfaildisp8 call printmsg nexttest: add oper2, 80h cmp oper2, 0 jnz loopmain mov si, offset dot call printmsg add oper1, 80h cmp oper1, 0h jnz loopmain mov si, offset strgood call printmsg finished: ret pass: mov si, offset strgood call printmsg ret fail: mov si, offset strfail call printmsg jmp finished printmsg: mov ah, 0Eh cld lodsb cmp al, 0 jz done int 10h jmp printmsg done: ret banner db '8086 CPU effective address calculation test utility',13,10 db 'Written on 3/4/2011 by Mike Chambers',13,10,13,10 db 'Testing EA calcs, this may take several minutes.',13,10 db 'Testing addressing modes', 0 strgood db 'passed!',13,10,0 strfail db 'FAILED!',13,10,0 dot db '.',0 strfailbxsi db 'failure in [BX+SI]',13,10,0 strfailbxdi db 'failure in [BX+DI]',13,10,0 strfailbpsi db 'failure in [BP+SI]',13,10,0 strfailbpdi db 'failure in [BP+DI]',13,10,0 strfailsi db 'failure in [SI]',13,10,0 strfaildi db 'failure in [DI]',13,10,0 strfaildisp16 db 'failure in [BX+Disp16]',13,10,0 strfaildisp8 db 'failure in [BX+Disp8]',13,10,0 strfailbx db 'failure in [BX]',13,10,0 oper1 dw 0 oper2 dw 0 disp dw 0 and here's another one to test your conditional branching: Code: ; branch.asm - A program to test the Intel 8086 CPU's
; various conditional branching operations. Designed to ; verify corrent functionality of my 8086 PC emulator, Fake86. org 100h cli push cs pop ds mov si, offset banner call printmsg testjc: mov si, offset strjc call printmsg call blankflags call setcf jc testjc2 call fail jmp testjnc testjc2: call blankflags mov bx, offset testjnc push bx jc fail pop bx ;not used, just cleaning up the stack call pass testjnc: mov si, offset strjnc call printmsg call blankflags jnc testjnc2 call fail jmp testjz testjnc2: call blankflags call setcf mov bx, offset testjz push bx jnc fail pop bx call pass testjz: mov si, offset strjz call printmsg call blankflags call setzf jz testjz2 call fail jmp testjnz testjz2: call blankflags mov bx, offset testjnz push bx jz fail pop bx call pass testjnz: mov si, offset strjnz call printmsg call blankflags jnz testjnz2 call fail jmp testjs testjnz2: call blankflags call setzf mov bx, offset testjs push bx jnz fail pop bx call pass testjs: mov si, offset strjs call printmsg call blankflags call setsf js testjs2 call fail jmp testjns testjs2: call blankflags mov bx, offset testjns push bx js fail pop bx call pass testjns: mov si, offset strjns call printmsg call blankflags jns testjns2 call fail jmp testjo testjns2: call blankflags call setsf mov bx, offset testjo push bx jns fail pop bx call pass testjo: mov si, offset strjo call printmsg call blankflags call setof jo testjo2 call fail jmp testjno testjo2: call blankflags mov bx, offset testjno push bx jo fail pop bx call pass testjno: mov si, offset strjno call printmsg call blankflags jno testjno2 call fail jmp testjp testjno2: call blankflags call setof mov bx, offset testjp push bx jno fail pop bx call pass testjp: mov si, offset strjp call printmsg call blankflags call setpf jp testjp2 call fail jmp testjnp testjp2: call blankflags mov bx, offset testjnp push bx jp fail pop bx call pass testjnp: mov si, offset strjnp call printmsg call blankflags jnp testjnp2 call fail jmp testja testjnp2: call blankflags call setpf mov bx, offset testja push bx jnp fail pop bx call pass testja: mov si, offset strja call printmsg call blankflags ;case 1 ja testja2 call fail jmp testjbe testja2: ;case 2 call blankflags call setcf mov bx, offset testjbe push bx ja fail pop bx testja3: call blankflags call setzf mov bx, offset testjbe push bx ja fail pop bx testja4: call blankflags call setcf call setzf mov bx, offset testjbe push bx ja fail pop bx call pass testjbe: mov si, offset strjbe call printmsg call blankflags ;case 1 call setcf jbe testjbe2 call fail jmp testjg testjbe2: call blankflags call setzf jbe testjbe3 call fail jmp testjg testjbe3: call blankflags call setcf call setzf jbe testjbe4 call fail jmp testjg testjbe4: call blankflags mov bx, offset testjg push bx jbe fail pop bx call pass testjg: mov si, offset strjg call printmsg call blankflags jg testjg2: call fail jmp testjge testjg2: call blankflags call setzf mov bx, offset testjge push bx jg fail pop bx testjg3: call blankflags call setsf call setzf mov bx, offset testjge push bx jg fail pop bx testjg4: call blankflags call setof call setzf mov bx, offset testjge push bx jg fail pop bx testjg5: call blankflags call setsf call setof call setzf mov bx, offset testjge push bx jg fail pop bx testjg6: call blankflags call setsf call setof mov bx, offset testjge push bx jg pass pop bx call fail testjge: mov si, offset strjge call printmsg call blankflags jge testjge2 call fail jmp testjl testjge2: call blankflags call setsf mov bx, offset testjl push bx jge fail pop bx testjge3: call blankflags call setof mov bx, offset testjl push bx jge fail pop bx call pass testjl: mov si, offset strjl call printmsg call blankflags call setsf jl testjl2 call fail jmp testjle testjl2: call blankflags call setof jl testjl3 call fail jmp testjle testjl3: call blankflags call setsf call setof mov bx, offset testjle push bx jl fail pop bx testjl4: call blankflags mov bx, offset testjle push bx jl fail pop bx call pass testjle: mov si, offset strjle call printmsg call blankflags call setzf jle testjle2 call fail jmp finished testjle2: call blankflags call setsf jle testjle3 call fail jmp finished testjle3: call blankflags call setof jle testjle4 call fail jmp finished testjle4: call blankflags call setsf call setzf jle testjle5 call fail jmp finished testjle5: call blankflags call setof call setzf jle testjle6 call fail jmp finished testjle6: call blankflags call setsf call setof call setzf jle testjle7 call fail jmp finished testjle7: call blankflags mov bx, offset finished push bx jle fail call pass finished: ret pass: mov si, offset strgood call printmsg ret fail: mov si, offset strfail call printmsg ret blankflags: xor ax, ax push ax popf ret setcf: stc ret setof: pushf pop ax or ah, 00001000b push ax popf ret setsf: pushf pop ax or al, 10000000b push ax popf ret setzf: pushf pop ax or al, 01000000b push ax popf ret setpf: pushf pop ax or al, 00000100b push ax popf ret printmsg: mov ah, 0Eh cld lodsb cmp al, 0 jz done int 10h jmp printmsg done: ret banner db '8086 CPU conditional branch test utility',13,10 db 'Written on 3/4/2011 by Mike Chambers',13,10,13,10,0 strjc db 'Testing JC/JB/JNAE (jump if CF=1)... ',0 strjnc db 'Testing JNC/JNB/JAE (jump if CF=0)... ',0 strjz db 'Testing JZ/JE (jump if ZF=1)... ',0 strjnz db 'Testing JNZ/JNE (jump if ZF=0)... ',0 strjs db 'Testing JS (jump if SF=1)... ',0 strjns db 'Testing JNS (jump if SF=0)... ',0 strjo db 'Testing JO (jump if OF=1)... ',0 strjno db 'Testing JNO (jump if OF=0)... ',0 strjp db 'Testing JP/JPE (jump if PF=1)... ',0 strjnp db 'Testing JNP/JPO (jump if PF=0)... ',0 strja db 'Testing JA/JNBE (jump if CF=0 and ZF=0)... ',0 strjbe db 'Testing JBE/JNA (jump if CF=1 or ZF=1)... ',0 strjg db 'Testing JG/JNLE (jump if SF=OF and ZF=0)... ',0 strjge db 'Testing JGE/JNL (jump if SF=OF)... ',0 strjl db 'Testing JL/JNGE (jump if SF<>OF)... ',0 strjle db 'Testing JLE/JNG (jump if SF<>OF or ZF=1)... ',0 strgood db 'passed!',13,10,0 strfail db 'FAILED!',13,10,0 |
Author: | miker00lz [ Fri Jun 17, 2011 1:14 pm ] |
Post subject: | Re: an 8086 PC emulator |
berkus wrote: miker00lz wrote: alsooooooo... i added attack and decay to my adlib code http://rubbermallet.org/fake86-adlib(attack-decay).mp3 Sounds good! thanks. it's generating square waves though, and i think i should change it to sine. |
Author: | miker00lz [ Fri Jun 17, 2011 1:22 pm ] |
Post subject: | Re: an 8086 PC emulator |
i've got a question i'm hoping somebody has a solution for.. to keep track of timing (needs to be extremely precise) i've been using QueryPerformanceCounter() for windows builds, and clock_gettime (with CLOCK_REALTIME) for linux builds. they are definitely precise enough, but i hate the fact that i need to waste so much CPU to poll these so often. they are extremely slow. what i really want is a roughly microsecond-accurate timer that triggers interrupts which i can use too hook onto a callback function. am i out of luck with this? surely there must be some way to do this with the windows and linux APIs?... and i'd like to keep it compatible with relatively recent versions of windows, ideally all the way back to win2k. something running an older windows than that is probably not the kind of system you want to run a PC emulator on... EDIT: i was thinking that on x86 hosts, i could just branch a thread to keep doing CPUID+RDTSC with inline asm and lock it to a single CPU core but i want to make it portable. |
Author: | Artlav [ Fri Jun 17, 2011 2:27 pm ] |
Post subject: | Re: an 8086 PC emulator |
Nice work. If you're interested, here is my collection of testsuites for EPC's 80186: http://orbides.1gb.ru/80186_tests.zip res_*.bin contains the results expected at the offset 0x0 when you run *.bin test placed as a BIOS. Although, if you have win 3.0 booting these are a little late. About the timing - do you want to get precise real-time experience or something? You won't get away from CPU overuse without many tricks. There is nothing better then scheduling to free the CPU (like sleep(1);), but it's hard to predict the duration. Best results will be with rdtsc and active waiting, but you're still subjected to task switching. Why bother? |
Author: | miker00lz [ Fri Jun 17, 2011 3:42 pm ] |
Post subject: | Re: an 8086 PC emulator |
Artlav wrote: Nice work. If you're interested, here is my collection of testsuites for EPC's 80186: http://orbides.1gb.ru/80186_tests.zip res_*.bin contains the results expected at the offset 0x0 when you run *.bin test placed as a BIOS. Although, if you have win 3.0 booting these are a little late. About the timing - do you want to get precise real-time experience or something? You won't get away from CPU overuse without many tricks. There is nothing better then scheduling to free the CPU (like sleep(1);), but it's hard to predict the duration. Best results will be with rdtsc and active waiting, but you're still subjected to task switching. Why bother? yeah the timing is for generating the real-time clock interrupt, as well as generating audio samples for output at the proper intervals. also, that link you gave is a 404. even though i've got win 3.0 booting, i'd still like to run it and see what happens. thanks. |
Author: | Artlav [ Sat Jun 18, 2011 6:59 am ] |
Post subject: | Re: an 8086 PC emulator |
Try again, i don't usually delete hosted files, so i didn't bother to check. About timer/RTC interrupt - isn't it related only to the CPU? There should be a clock counter in CPU emulation, based on instructions executed, and the interrupt is called based on that. You can then pad the CPU to average it at a given clock rate per real second, and you'll get a real-time system. About the sound - no ideas, never implemented it. |
Author: | miker00lz [ Sat Jun 18, 2011 11:33 am ] |
Post subject: | Re: an 8086 PC emulator |
Artlav wrote: Try again, i don't usually delete hosted files, so i didn't bother to check. About timer/RTC interrupt - isn't it related only to the CPU? There should be a clock counter in CPU emulation, based on instructions executed, and the interrupt is called based on that. You can then pad the CPU to average it at a given clock rate per real second, and you'll get a real-time system. About the sound - no ideas, never implemented it. no the timer interrupt is based on a 1,193,180 Hz master clock regardless of CPU speed. it's divided by the value that you program into PIT channel 0. a PC's BIOS initially sets the dividier to 65536, which is 18.2 Hz. games often change it to go faster. for the audio, i'm using it to generate correct frequencies for the PC speaker and adlib channels based on sample rate divided by output freq per channel. it's working well as i have it, i was just hoping for a less CPU intensive method than constant polling. also, i got the tests zip. thanks! |
Author: | miker00lz [ Fri Jun 24, 2011 6:06 pm ] |
Post subject: | Re: an 8086 PC emulator |
big update.. so, i've uploaded a current snapshot which should be considered unstable, but it's got Adlib emulation (not the greatest yet), plus Disney Sound Source, PC speaker, and networking support. if anybody wants to try it and let me know how it works for them, that would be awesome. some programs dont like work with the networking yet for some reason, for example arachne. i'm trying to find out why. some things run fine with it. my announcement of it with more detailed info: http://fake86.rubbermallet.org/?articles/2011/06/24/uploaded-an-unstable-release download the win32 compiled binaries package: http://fake86.rubbermallet.org/?downloads/downloading-fake86-0-11-6-24-win32-zip or, if you're on linux, the source tarball. run build.sh in it: http://fake86.rubbermallet.org/?downloads/downloading-fake86-0-11-6-24-tar-gz you must have the libsdl 1.2 development library installed to compile. in debian/ubuntu - apt-get install libsdl1.2-dev and here is a 20 MB sample hard drive image with FreeDOS pre-installed, along with Wolfenstein 3D (which is really nice now with complete sound) and some other games: http://fake86.rubbermallet.org/?downloads/downloading-fake86_drive-7z ^extract that to the folder you have the fake86 binary in and run fake86 -hd0 drive.raw have fun! the code is quick enough to play Wolf3D smoothly on a 1 GHz pentium 3. |
Author: | ASMMan [ Sat Jan 19, 2013 12:02 am ] |
Post subject: | Re: an 8086 PC emulator |
Thanks for share it. Great job,man. I really like it. I'm performing some testing now. I been to able to run MS-DOS. I explored it,really. I played the game that you included thanks. But I'm not able to run a small kernel write with as86(by the way, what assembler are you using?) assembler. It run fine in my computer. I have maked the .iso file by using dd and mkisofs UNIX's programs combination. And so I write it to a CD-ROM. Ran fine as I've mentioned. By in the fake86 it disn't work. By default it doesn't print any error message(right?) and so I was looking for some way to get some state of current running process. I added the -verbose flag and I can see Code: Set video mode 30h Set video mode 20h Set video mode 07h Set video mode 03h Illegal opcode: 65 @ 0000:0108 Illegal opcode: 65 @ F000:E03B Illegal opcode: 65 @ F000:E03B Illegal opcode: 65 @ F000:E03B Illegal opcode: 65 @ F000:E03B Set video mode 00h why I'm getting this errors messages? what does this that mean? Code: entry start start: mov ax,#0xb800 mov es,ax seg es mov [0],#0x41 seg es mov [1],#0x1f loop1: jmp loop1 The OS code is very very simple. Just print the 'a' letter in black color with blue background. I have get it from a page in the internet. A tutorial that I have read. This is as86 syntax; I had never touched it before. I have make the file with: Code: as86 boot.s -o boot.o ld86 -d boot.o -o boot boot.s is the above assembly code. Another thing that I noticed,sometimes the emulator doesn't run correctly and exit because a segmentation fault error has been happened. As it just happen sometimes,I think that we have an UB in your C program? and +1 thanks for provide a easy-to-install program. Unlike almost all linux programs where usually you enter in a stupid iteration of miss-packages. Not all cases a programs such as apt-get and zypper are enough. Also, I'm a C programmer. I will read the source code. If a can provide some help to emulator, I will do. (sorry for my bad english; not my native language speaker) |
Author: | ASMMan [ Sun Jan 20, 2013 6:43 pm ] |
Post subject: | Re: an 8086 PC emulator |
I solved the problem of 'Ilegal opcodes'. It's fine now. The problem was because I had not put the PC signature in the binary file. 0x55 and 0xAA at byte 511 and 512 respectively. I have another question,not sure if an error in the program. But sometimes the emulator open the emulator itself in full screen mode,even if -fullscreen isn't passed in the command-line-options. And when it happens,I have no idea how to get out from there. My GUI environment is KDE,CTRL+ESC open the system process management,but it doesn't work. But after release the mouse by ctrl+alt keys combination and then I need to force the computer to reboot. Also,thanks so much again for share it this program. I'm looking for sometime to contribute by some way. |
Page 2 of 2 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |