Actual implementation of the int 3d call (Standalone FWAIT) is to patch the code to an fwait(9b) and a noop(90).
It seems that it corrupts the stack in FPU_ModifyCode and prevents vb3 programs to start. (tests made with current CVS)
Since we do nothing apart an emulated fwait, I commented the call to FPU_ModifyCode. The call to int3d is equal to nothing and makes vb3 programs start :
dlls/winedos/fpu.c : 188 TRACE("Int 0x3d called-- Standalone FWAIT"); /* FPU_ModifyCode(context, 0x90); */
Does it seems to you its the correct way to proceed and will it be valid in all cases ?
===== Sylvain Petreolle (spetreolle_at_users_dot_sourceforge_dot_net) ICQ #170597259
alias upsf='false ; while [ $? -ne 0 ] ; do cvs update -APd ; done 2>&1 |tee cvslog'
"What if tomorrow the War could be over ?" Morpheus, in "Reloaded".
___________________________________________________________ Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français ! Yahoo! Mail : http://fr.mail.yahoo.com
Sylvain Petreolle,
Actual implementation of the int 3d call (Standalone FWAIT) is to patch the code to an fwait(9b) and a noop(90).
This is what emmulators do when a real FPU is present in the system. With wine, it is safe to assume that an FPU of some kind will always be present so replacing the code in the program with the direct FPU calls is the correct procedure. The problem is most likely that I miscalculated the offsets on the stack. On the return, I have to either back up or increment the instruction pointer so that the FPU instructions are either executed from the program or skipped, respectively. Since there is no wine function for converting flat to segment:offset addresses, I just did my best to hit the right point on program return and execute FPU instructions.
It seems that it corrupts the stack in FPU_ModifyCode and prevents vb3 programs to start. (tests made with current CVS)
Can you tell me the addresses in the IP register at the time of call and return to the program? I must have either miscalculated the backup or failed to account to movement between memory segments. Skipping the code works with the fwait, however, the other FPU instructions will not be that easy to handle.
God Bless You, --Robert 'Admiral' Coeyman
Can you tell me the addresses in the IP register at the time of call
and
return to the program? I must have either miscalculated the backup
or failed
to account to movement between memory segments. Skipping the code works with the fwait, however, the other FPU instructions will not be
that easy
to handle.
After doing some winedbg work, it appears that : - my call appears at 0x36f:0xc and should return at 0x36f:0xe Wine-dbg>disass 0x36f:0xc 0x036f:0x0000000c: int $0x3d 0x036f:0x0000000e: movw 0xfffffffc(%bp),%ax 0x036f:0x00000011: movw 0xfffffffe(%bp),%dx 0x036f:0x00000014: leave 0x036f:0x00000015: ret $0x4
after setting a breakpoint on DOSVM_Int3dHandler, I see that your calculated code variable points to another place (if I am right ;))
192 FPU_ModifyCode(context, 0x90); Wine-dbg>step 225 WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); Wine-dbg> 224 { Wine-dbg> 225 WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); Wine-dbg> 226 BYTE *code = CTX_SEG_OFF_TO_LIN(context, stack[1], stack[0]); Wine-dbg> 232 code[-2] = 0x9b; /* The fwait instruction */ Wine-dbg>disass code-2 0x000d0b51: addb $0,%al 0x000d0b53: int $0x31 0x000d0b55: sti 0x000d0b56: lret
One things appears strange to me : you use a WORD pointer for the stack. Shouldnt it be a DWORD pointer, since real mode uses dword stack ?
God Bless You, --Robert 'Admiral' Coeyman
===== Sylvain Petreolle (spetreolle_at_users_dot_sourceforge_dot_net) ICQ #170597259
alias upsf='false ; while [ $? -ne 0 ] ; do cvs update -APd ; done 2>&1 |tee cvslog'
"What if tomorrow the War could be over ?" Morpheus, in "Reloaded".
___________________________________________________________ Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français ! Yahoo! Mail : http://fr.mail.yahoo.com
Sylvain Petreolle,
After doing some winedbg work, it appears that :
- my call appears at 0x36f:0xc and should return at 0x36f:0xe
Wine-dbg>disass 0x36f:0xc 0x036f:0x0000000c: int $0x3d 0x036f:0x0000000e: movw 0xfffffffc(%bp),%ax 0x036f:0x00000011: movw 0xfffffffe(%bp),%dx 0x036f:0x00000014: leave 0x036f:0x00000015: ret $0x4
After the call, the return pointer should return execution to 0x36f:0xc which will then contain the actual FPU opcode written over the interrupt call. In the case of an fwait, which we can safely ignore on 32 bit systems, 0xcd3d could become 0x9090. That is just two NOP instructions and would do nothing but take up space. The return pointer on the stack then has to be set back for all of the FPU instructions so that the opcode that replaced the interrupt call will be executed.
after setting a breakpoint on DOSVM_Int3dHandler, I see that your calculated code variable points to another place (if I am right ;))
It should be changed so that it points back to the changed interrupt call instead of the next instruction.
192 FPU_ModifyCode(context, 0x90); Wine-dbg>step 225 WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); Wine-dbg> 224 { Wine-dbg> 225 WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); Wine-dbg> 226 BYTE *code = CTX_SEG_OFF_TO_LIN(context, stack[1], stack[0]); Wine-dbg> 232 code[-2] = 0x9b; /* The fwait instruction */ Wine-dbg>disass code-2 0x000d0b51: addb $0,%al 0x000d0b53: int $0x31 0x000d0b55: sti 0x000d0b56: lret
One things appears strange to me : you use a WORD pointer for the stack. Shouldnt it be a DWORD pointer, since real mode uses dword stack ?
I'm using a word because I am trying to split the segment word and the offset word. My references show the stack, in real mode, as 4 bytes with two being the offset and two being the segment. The whole problem results from trying to alter this return address in real mode where I have to modify the address as two parts. Maybe there is a difference under wine. God Bless, --Robert 'Admiral' Coeyman
Seems we have all dword pointers on the stack. This is the stack I have for the DOSVM_EmulateInterruptPM call, Cs and Eip have been pushed on the stack. 0x36f and 0xc are the location the location of the call to the interrupt.
Wine-dbg>info stack Stack dump: 0x41a60948 (_end+0x10bff4): 4008de8b 41a60a44 0000003d 00000000 0x41a60958 (_end+0x10c004): 40016720 00010206 0000036f 0000000c ... Wine-dbg>disass 0x36f:0xc 0x036f:0x0000000c: int $0x3d 0x036f:0x0000000e: movw 0xfffffffc(%bp),%ax
I'm using a word because I am trying to split the segment word and the offset word. My references show the stack, in real mode, as 4
bytes with
two being the offset and two being the segment. The whole problem
results from
trying to alter this return address in real mode where I have to
modify the
address as two parts. Maybe there is a difference under wine. God Bless, --Robert 'Admiral' Coeyman
===== Sylvain Petreolle (spetreolle_at_users_dot_sourceforge_dot_net) ICQ #170597259
alias upsf='false ; while [ $? -ne 0 ] ; do cvs update -APd ; done 2>&1 |tee cvslog'
"What if tomorrow the War could be over ?" Morpheus, in "Reloaded".
___________________________________________________________ Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français ! Yahoo! Mail : http://fr.mail.yahoo.com