c++ - Porting a 16-bit DOS program to windows, and inline asm which uses
SL <shadowlord13 users.sourceforge.net> writes:
Quoting from http://www.digitalmars.com/ctg/ctgInlineAsm.html:Functions can change the values in the EAX, ECX, EDX, ESI, EDI >registers. Functions must preserve the values in the EBX, ESI, EDI, EBP, ESP, SS, CS, DS registers (plus ES and GS for the NT memory model).
I'm attempting to port a 16-bit DOS program (which is compiled for DOS with Borland's C++ 3.1 compiler) to Windows, using DMC as the windows compiler. This program is written in C++, but doesn't use classes, and uses a LOT of assembly code. I've already modified the asm so it should work, and the rest of the program (I'll elaborate on what I had to do if anyone wants to know, otherwise, it's probably not relevant), and it compiles fine. (Semi-important note: The code does not modify any segment registers at all when compiled for windows, doesn't use lds/les/etc, and so forth) However, there's a problem (possibly a compiler bug). This program uses EBX (a lot), EDI and ESI (also a lot), and also in one place it uses EBP. It does push/pop the values around the code that uses them, and this all works fine in BC3.1, but I'll need to check the one spot where it uses ebp to make sure it isn't using any local variables there. However, it seems that references to someLocalArray[esi] in inline asm code are being assembled wrong: Original inline asm: fld dword ptr trxf fld dword ptr trxf fsub dword ptr trxf[esi] What's actually in the EXE: fld dword ptr [ebp-0x44] //ebp is 0012fbc0 when that's run fld dword ptr [ebp-0x40] fsub dword ptr [esi-0x44] trxf is an array that's declared at the top of that function: float trxf; esi is 12 when that code is being run (It'll be always set to either 8 or 12 there). So trxf[esi] should be getting assembled to [ebp-0x44+esi], shouldn't it (or [esi-0x44+ebp], whatever)? (Instead of [esi-0x44]) Is that a bug in the compiler/assembler/whatever-is-doing-this? P.S. That code works fine in DOS, of course, though it uses si instead of esi. And I had one other question: What does DMC use EBX and EDI and ESI for? Can I get away with pushing them before doing asm code and popping them after? That's how it's coded now. I'm hoping that they're all used only at the start and end of functions, or for classes, say, as a pointer to the current object when executing a class method. This program doesn't use classes at all, and only uses structs in a few places. The author actually relied in a few places on variables being placed in memory in the order they're declared in, so he could save them all to disk or load them all in one _read or _write statement. That works fine in BC.31, but I wonder if it will in DMC. No worries though, if they aren't arranged in order of declaration, I'll just have to either load them one at a time or shove them into a struct temporarily to load or save them. Thanks in advance for your time & help. -SL
Feb 27 2005
SL <shadowlord13 gmail.com> writes:
My original report was for 8.41, but the problem also exists in the 8.42 beta (which I downloaded yesterday and tried today). Additionally, this might help track down the problem: Note: MAYBE_ESI is #define'd to esi in windows and si in DOS, and MAYBE_EDI to edi in windows, etc. Note #2: As I also stated in my previous post, trxf is a local variable defined as 'float trxf'. These lines of asm code assemble as follows: Original asm code Assembles to ----------------- ------------ fsub dword ptr [trxf] d865bc fsub dword ptr [ebp-0x44] fsub dword ptr trxf[MAYBE_ESI] d866bc fsub dword ptr [esi-0x44] fsub dword ptr [trxf+MAYBE_ESI] d866bc fsub dword ptr [esi-0x44] fsub dword ptr trxf[MAYBE_EDI] d867bc fsub dword ptr [edi-0x44] fsub dword ptr [trxf+MAYBE_EDI] d867bc fsub dword ptr [edi-0x44] fsub dword ptr trxf[MAYBE_EAX] d860bc fsub dword ptr [eax-0x44] fsub dword ptr [trxf+MAYBE_EAX] d860bc fsub dword ptr [eax-0x44] fsub dword ptr trxf[MAYBE_EBX] d863bc fsub dword ptr [ebx-0x44] fsub dword ptr [trxf+MAYBE_EBX] d863bc fsub dword ptr [ebx-0x44] fsub dword ptr trxf[MAYBE_ECX] d861bc fsub dword ptr [ecx-0x44] fsub dword ptr [trxf+MAYBE_ECX] d861bc fsub dword ptr [ecx-0x44] fsub dword ptr trxf[MAYBE_EDX] d862bc fsub dword ptr [edx-0x44] fsub dword ptr [trxf+MAYBE_EDX] d862bc fsub dword ptr [edx-0x44] So [localVariable] is assembled correctly, but none of the others are. Omitting 'dword ptr' from the asm doesn't affect the assembled code (not that it should). I tried one last thing as a workaround: fsub dword ptr trxf[ebp+MAYBE_ESI] d86435bc fsub dword ptr [ebp+esi-0x44] fsub dword ptr [trxf+ebp+MAYBE_ESI] d86435bc fsub dword ptr [ebp+esi-0x44] So that compiled to what we were looking for originally, but amounted to artificially adding the missing ebp back, so when this bug gets fixed, I expect the workaround asm would probably either cause a compile-time error or turn into 'fsub dword ptr [ebp*2+esi-0x44]'. :P One more clarification: I have not compiled the program for DOS with DMC and checked to see if these compile right, and do not plan to at this time (It's a 16-bit program, and compiling it for DOS with BC 3.1 produces smaller EXEs and compiles properly, whereas DMC tends to push several of the code segments over the 64 KB limit, forcing functions to be moved around, with the end result being an EXE which was big enough that it didn't have enough RAM for its data-arrays). -SL
Feb 28 2005
"Walter" <newshound digitalmars.com> writes:
"SL" <shadowlord13 gmail.com> wrote in message news:d00b77$11uq$1 digitaldaemon.com...I tried one last thing as a workaround: fsub dword ptr trxf[ebp+MAYBE_ESI] d86435bc fsub dword ptr [ebp+esi-0x44] fsub dword ptr [trxf+ebp+MAYBE_ESI] d86435bc fsub dword ptr [ebp+esi-0x44] So that compiled to what we were looking for originally, but amounted to artificially adding the missing ebp back, so when this bug gets fixed, I expect the workaround asm would probably either cause a compile-time error or turn into 'fsub dword ptr [ebp*2+esi-0x44]'. :P
It's a different behavior than BC, not a bug. The general idea is that if you're using the indexing addressing mode, you need to say which registers are being used. The compiler just replaces trxf with the offset from EBP, the rest is up to you. It isn't likely to change, as I'm not up to breaking lots of existing inline asm code!
Feb 28 2005
SL <shadowlord13 gmail.com> writes:
Ah. Well, thanks for your time. I'm happy as long as I can count on it to stay the same in future versions. Now I just need to find all the places where the asm code does that kind of thing... (Of course, an optional compiler flag to always include ebp could be useful to anyone porting things from BC, and wouldn't affect existing inline asm code - Though there are already a lot of compiler flags, and maybe that's too special-case to deserve one) -SL
Mar 01 2005