Hi guys, I was working on my emulator. I am now working on Sega Genesis support.

Also, it's been quite a while since I have visited this site! Been playing with FPGA's and VHDL and ya long story.

Anyway, I loaded a game and was running the game only to find out that it CRASHED (M68K stopped processing and was thrown into an infinite loop, the developers have all error vectors pointing to the same location). Now before you slam me and say it is an error in my 68K emulator, I would like to inform you that the game DOES NOT crash when NOT being debugged by MSVC.

So using some of the features I built into the 68K emulator, I isolated the bug to a small function within the game code:

              move.l  (a3),(a4)
              move.l  $70(a3),(a4)
              move.l  $E0(a3),(a4)
              move.l  $150(a3),(a4)


My 68K emulator executes these opcodes correctly, but the first one (with $70 in it) corrupts the 68K's PC. So I went and observed the assembly code that performs these instructions and have it as listed:

00741524 8D 6E 20          lea        ebp,
00741527 8B 5C 95 00      mov        ebx,dword ptr
0074152B 03 D8              add        ebx,eax
0074152D 89 4E 48          mov        dword ptr ,ecx


I think I should take the time to note now, that my 68K emulator was assembled my MASM 6.14 I believe as a LIB and was linked into my VC++ project.

I stepped through and noticed that the ADD EBX,EAX does something weird. IT DESTROYS ECX!!! I am using that register to keep track of the 68K's current PC.

Register State Before ADD EBX,EAX:

EAX = 00000070 EBX = 00FF81C0 ECX = 0003367E EDX = 00000003
ESI = 00928CA8 EDI = 09F60040 EIP = 0074152B ESP = 0012FC10
EBP = 00928CC8 EFL = 00200206



Register State AFTER ADD EBX,EAX:

EAX = 00000070 EBX = 00FF81C0 ECX = 0016328E EDX = 00000003
ESI = 00928CA8 EDI = 09F60040 EIP = 0074152D ESP = 0012FC10
EBP = 00928CC8 EFL = 00200206


As you can see, EBX remains unmodified (incorrect) and ECX has been replaced with garbage.  :shock:

Now, I am posting here to see if there is something I may be overlooking?! No I am not running multithreaded code (but DirectSound does seem to create threads on initialization).

Sorry if this is in the wrong place mods and hiroshimator(sp?), I havent been here for approx a yr and didnt know where to post!!

My basic system specs:

AThlonXP 2500+ @ 2.2Ghz
768MB RAM
Win2K SP4.


I will try and see if it responds in a similar manner on my Thinkpad.
My Thinkpad T23 is running WinXP SP2.
Posted on 2006-03-26 00:38:37 by x86asm
This sounds *pretty* strange. Can yougive some more lines of context before and after? Also, some of the C/C++ code interfacing with the assembly could be helpful.

I don't think I've seen anything like this with vc2003, it generates pretty good code and the compiler seems pretty stable...

stray thought: are you (m)assembling with debug info turned on? and have you tried disassembling the object file with the offending code and see if it really is what you think it is? (freeware version of IDA should do just fine).
Posted on 2006-03-26 04:34:10 by f0dder


This sounds *pretty* strange. Can you give some more lines of context before and after? Also, some of the C/C++ code interfacing with the assembly could be helpful.

I don't think I've seen anything like this with vc2003, it generates pretty good code and the compiler seems pretty stable...

stray thought: are you (m)assembling with debug info turned on? and have you tried disassembling the object file with the offending code and see if it really is what you think it is? (freeware version of IDA should do just fine).



Hi f0dder long time no see  :D

Yes sure I will post some more details, I am posting on my laptop so I don't have it available now. Yes I really like VC2003, it has been very good to me up to now. This is the only incident I've had with it.

I am assembling the LIB and the app with debug info enabled. I haven't tried disassembling the object code, I will try that and see.
At first I thought maybe it was the wrong opcode, so I put two db bytes in a small project and used OllyDbg and it came out right. So it is really confusing me  :mad:
Posted on 2006-03-26 10:00:02 by x86asm
OK I'm on my main PC, I will post here before I go and play Path of Neo, great game if you like the Matrix series.

OK here is some context around the code, I will add some comments wherever I can

0074150F 0F B7 04 38      movzx      eax,word ptr
00741513 86 C4            xchg        al,ah
00741515 83 C1 02        add        ecx,2
00741518 8B 96 81 00 00 00 mov        edx,dword ptr
0074151E 83 E2 07        and        edx,7
00741521 0F BF C0        movsx      eax,ax
00741524 8D 6E 20        lea        ebp,
00741527 8B 5C 95 00      mov        ebx,dword ptr
0074152B 03 D8            add        ebx,eax
0074152D 89 4E 48        mov        dword ptr ,ecx
00741530 8B C3            mov        eax,ebx
00741532 25 FF FF FF 00  and        eax,0FFFFFFh
00741537 8B D8            mov        ebx,eax
00741539 C1 E8 10        shr        eax,10h
0074153C 25 FF 00 00 00  and        eax,0FFh
00741541 C1 E0 06        shl        eax,6
00741544 8B 6E 54        mov        ebp,dword ptr
00741547 03 E8            add        ebp,eax
00741549 F7 46 44 00 20 00 00 test        dword ptr ,2000h
00741550 74 03            je          00741555
00741552 83 C5 20        add        ebp,20h
00741555 8B 55 00        mov        edx,dword ptr
00741558 85 D2            test        edx,edx
0074155A 74 07            je          00741563
0074155C 8B 04 13        mov        eax,dword ptr
0074155F 0F C8            bswap      eax 
00741561 EB 23            jmp        00741586
00741563 89 5E 71        mov        dword ptr ,ebx
00741566 51              push        ecx 
00741567 53              push        ebx 
00741568 FF 55 08        call        dword ptr
0074156B 89 46 75        mov        dword ptr ,eax
0074156E 83 46 71 02      add        dword ptr ,2
00741572 FF 76 71        push        dword ptr
00741575 FF 55 08        call        dword ptr
00741578 C1 E0 10        shl        eax,10h
0074157B 81 66 75 FF FF 00 00 and        dword ptr ,0FFFFh
00741582 0B 46 75        or          eax,dword ptr
00741585 59              pop        ecx 
00741586 85 C0            test        eax,eax
00741588 0F 98 46 5D      sets        byte ptr
0074158C 0F 94 46 5E      sete        byte ptr
00741590 C6 46 5F 00      mov        byte ptr ,0
00741594 C6 46 60 00      mov        byte ptr ,0



I know the code is less than beautiful, but for my 68K emulator I wrote a C program to generate the ASM code. It made it a lot easier, I will optimize it a bit later. For now though, both the 68K and Z80 emulation times are less than a 3rd of what the CPU spends rendering the VDP stuff.

Now the code that makes the function call the 68K emulator is your plain vanilla STDCALL invocator.


0057D246 68 D0 8B 92 00  push        offset perfrd0 (928BD0h)
0057D24B FF 15 14 B6 00 01 call        dword ptr [__imp__QueryPerformanceCounter@4 (100B614h)]

Run68000(483);
0057D251 68 E3 01 00 00  push        1E3h
0057D256 E8 67 E4 FF FF  call        @ILT+1725(_Run68000@4) (57B6C2h)        ;68K emu invoke code
QueryPerformanceCounter(&perfrd1);
0057D25B 68 F8 F1 92 00  push        offset perfrd1 (92F1F8h)
0057D260 FF 15 14 B6 00 01 call        dword ptr [__imp__QueryPerformanceCounter@4 (100B614h)]

tstore0 = (__int64)perfrd1.QuadPart - (__int64)perfrd0.QuadPart;
0057D266 A1 F8 F1 92 00  mov        eax,dword ptr
0057D26B 2B 05 D0 8B 92 00 sub        eax,dword ptr
0057D271 8B 0D FC F1 92 00 mov        ecx,dword ptr
0057D277 1B 0D D4 8B 92 00 sbb        ecx,dword ptr
0057D27D A3 E8 ED 92 00  mov        dword ptr ,eax
0057D282 89 0D EC ED 92 00 mov        dword ptr ,ecx
tot68k+=tstore0;
0057D288 A1 30 8C 92 00  mov        eax,dword ptr
0057D28D 03 05 E8 ED 92 00 add        eax,dword ptr
0057D293 8B 0D 34 8C 92 00 mov        ecx,dword ptr
0057D299 13 0D EC ED 92 00 adc        ecx,dword ptr
0057D29F A3 30 8C 92 00  mov        dword ptr ,eax
0057D2A4 89 0D 34 8C 92 00 mov        dword ptr ,ecx



QueryPerformanceCounter(&perfrd0);
0057D2AA 68 D0 8B 92 00  push        offset perfrd0 (928BD0h)
0057D2AF FF 15 14 B6 00 01 call        dword ptr [__imp__QueryPerformanceCounter@4 (100B614h)]
UpdatePSG(228);
0057D2B5 68 E4 00 00 00  push        0E4h
0057D2BA E8 97 E6 FF FF  call        UpdatePSG (57B956h)
0057D2BF 83 C4 04        add        esp,4
QueryPerformanceCounter(&perfrd1);
0057D2C2 68 F8 F1 92 00  push        offset perfrd1 (92F1F8h)
0057D2C7 FF 15 14 B6 00 01 call        dword ptr [__imp__QueryPerformanceCounter@4 (100B614h)]

tstore0 = (__int64)perfrd1.QuadPart - (__int64)perfrd0.QuadPart;
0057D2CD A1 F8 F1 92 00  mov        eax,dword ptr
0057D2D2 2B 05 D0 8B 92 00 sub        eax,dword ptr
0057D2D8 8B 0D FC F1 92 00 mov        ecx,dword ptr
0057D2DE 1B 0D D4 8B 92 00 sbb        ecx,dword ptr
0057D2E4 A3 E8 ED 92 00  mov        dword ptr ,eax
0057D2E9 89 0D EC ED 92 00 mov        dword ptr ,ecx
totsnd+=tstore0;
0057D2EF A1 88 8C 92 00  mov        eax,dword ptr
0057D2F4 03 05 E8 ED 92 00 add        eax,dword ptr
0057D2FA 8B 0D 8C 8C 92 00 mov        ecx,dword ptr
0057D300 13 0D EC ED 92 00 adc        ecx,dword ptr
0057D306 A3 88 8C 92 00  mov        dword ptr ,eax
0057D30B 89 0D 8C 8C 92 00 mov        dword ptr ,ecx



Here is the code that invokes the 68K emulator. Sorry abou the mess, but the QueryPerformanceCounter code is actually used to determine how much time is spent in each area. Not perfect, but it indicates something (which is always better than nothing!!).

I have an inkling that I may be corrupting some memory somewhere unintentionally. I will have to track this down, also right after I make this post I will check if the instruction is really the right one at the point.


Yup, I just viewed the memory the correct opcode is there. So I must be corrupting memory somewhere?
I just noticed that my CPU seems to be performing an ADD EBX,ESP (Is this even valid?) not the requested ADD EBX, EAX.

Posted on 2006-03-26 13:51:11 by x86asm
Bahh, it did the exact same thing on my laptop. It seems like I maybe corrupting memory somewhere. I will look into it.

I am still open to suggestions in this desperate time!  :mad:
Posted on 2006-03-27 14:53:13 by x86asm
Hey, it was my fault!!

Anyways the particular game I was trying (Crusader of Centy) has some backed up RAM. The way my 68K emulator handles the region caused some problems (because I have a table of pointer bases for the 68K memory space, so the emulator simply adds the address to the base address and you have the x86 memory pointer).

I overwrote the region that defined the battery backed RAM and it seems that when the 68K wrote to the RAM to save the game, it corrupted memory somewhere!. It works now!

:lol:

I am sorry for bothering ya guys and thanks a lot f0dder for all your help! It seems to have steered me in the right direction.

Now to continue on with the YM2612 emulation, that is coming along quite nicely  :D
Posted on 2006-03-28 22:51:20 by x86asm
Sorry I wasn't around to try and help you, only just got ADSL today and had a *real* shitload of real-life related crap (check http://www.donationcoder.com/Forums/bb/index.php?topic=2933.0 in case you care). But nice that you got the problem solved :)
Posted on 2006-03-29 03:39:50 by f0dder

Sorry I wasn't around to try and help you, only just got ADSL today and had a *real* ****load of real-life related crap (check http://www.donationcoder.com/Forums/bb/index.php?topic=2933.0 in case you care). But nice that you got the problem solved :)



wow, you've been through hell and then some!
Posted on 2006-03-29 13:58:13 by x86asm
show us your emulator, x86asm
Posted on 2006-04-26 13:09:57 by comrade