Thanks for your kind answers for my question. I have a question for 8087. code is, finit fld1 fld1 fistp dword_tmp_1 ; dword data invoke PrintDword, dword_tmp_1 fistp dword_tmp_1 invoke PrintDword, dword_tmp_1 and PrintDword is as follows, PrintDword PROC C msg : DWORD PUSHA INVOKE wsprintfA, ADDR print_dword_text, ADDR print_dword_message_form, msg, msg INVOKE MessageBox, h_window, ADDR print_dword_text, ADDR print_dword_title, MB_OK POPA RET PrintDword ENDP I thought results must be messagebox of '01H', '01H' but the real results are '01H', '80000000H' Above, I load '1'(fld1) twice, and print it twice, but results are not what I wanted. What is my mistake? Help me. Thank you.
At a glance I believed you were getting these results because the 8087 (IEEE standard I think it called) does not use 01h as the binary representation of 1. But the second result of '80000000H' is not the hex version of 1.0 either, which is 3F800000h instead. So this is a bizzare problem. First try:
If this doesn't output the correct hex number then I'd say the problem lies elsewhere. Try using the dw2hex proc in the masmlib with masm32 to see if this solves the problem. Therefore indicating that the problem is with wsprintfA. If the above code does work then remove the second finit and try it again. If it fails here then the problem is very bizzare indeed. I've noticed a problem sometimes when loading a value onto the 8087 when there already five things there. For no apparent reason the value loaded on becomes FFC00000h. If, however the above code works then (and this is most likely the problem) wsprintfA must mess up the 8087 stack. In fact, unless its a programming error on your behalf, I'd bet money on this being the problem.
finit fld1 fistp dword_tmp_1 ; dword data invoke PrintDword, dword_tmp_1 finit fld1 fistp dword_tmp_1 invoke PrintDword, dword_tmp_1
Thank you for your reply. I tried after your advise(for problem for wprintfA), (fistp returns value in integer format (not in real format), so return value is '1' I expected.) finit fld1 fld1 fistp dword_tmp_1 cmp dword_tmp_1,1 jne tmp_loop_exit1 fistp dword_tmp_1 cmp dword_tmp_1,1 jne tmp_loop_exit2 invoke PrintDword,1 jmp tmp_loop_exit_3 tmp_loop_exit1: invoke PrintDword,999 jmp tmp_loop_exit_3 tmp_loop_exit2: invoke PrintDword,99999 tmp_loop_exit_3: The result is '1' (not 999, 99999) so if I don't use procedure PrintDword(contain 'wsprintfA'), the result is same what I expected. But I can not understand why PrintDword causes problem? (the source is listed above) I learned stacks of 8087(I used 80387) are different area from the area of 8086. Why PrintDword infest the area of 8087? I used PrintDword as hard coding tool(for debug, break point). I can not trust it now. You said dw2hex in masm32 library, but I only found dwtoa (to ascii format), and is it the function? >I've noticed a problem sometimes when loading a value >onto the 8087 when there already five things there. >For no apparent reason the value loaded on becomes >FFC00000h. Really? I thought the size of stack is 8, but why error occurs in 5~6 area? 8087 is not a good tool? Thanks very much.
it seems, that wsprintf touches the fpu state. Microsoft states for WINAPI like functions:
you must preserve the floating point control word and clean the coprocessor stacksince wsprintf is a (the one and only?) _cdecl function it may not keep to this. Maybe you can watch the fpu state with the debugger before and post wsprintf?
Yea it must be wsprintf thats affecting the fpu. As far as I know this command comes for C and I suppose technically since C based commands are not required to preserve CPU registers the they don't preserve 8087 state either. As I said I use dw2hex for this purpose, actually I rarely deal in hex and instead use either dwtoa (integer to ascii decimal) and FloatToString (Real8 to ascii decimal) All three of these commands come in the latest masm32. you probably have to install both service packs however and rebuild the library. Go to Hutchs site and download them. Theres very clear step by step instructions with them explaining how to install them properly (Just what I tend to need). These three routine do not affect 8087 so their very safe to use
I didn't test wsprintf but it probably clear the st(0) FPU register. Also, lstrcat and dwtoa clear the FPU. Then, you cannot rely that the FPU register will be at the same values after the call for that functions. I used this:
I put the original code of dwtoa inside my program to be available to debug. Ok, the registers of FPU remaind unchanged. But, MessageBox killed all the FPU values !! :( See the code:
.data szMsg01 BYTE "The first one: " ,0 szMsg02 BYTE "The second one: ",0 szCaption BYTE "This is a test" ,0 .data? buf128 BYTE 128 dup(?) buf24 BYTE 24 dup(?) dwValue DWORD ? .code ;************************************************** MainCode *** MainCode proc finit fld1 fistp dwValue invoke PrintDword,ADDR szMsg01,dwValue fld1 fistp dwValue invoke PrintDword,ADDR szMsg02,dwValue ret MainCode endp ;************************************************ PrintDword *** PrintDword proc lpMsg:DWORD,dwVal:DWORD ;Obs.: This routine uses: ; buf128 :128 bytes ; buf24 :24 bytes ; szCaption invoke lstrcat ,ADDR buf128,lpMsg ;join Msg with buf128 invoke dwtoa ,dwVal,ADDR buf24 ;convert dwVal to ASCII invoke lstrcat ,ADDR buf128,ADDR buf24 ;join buf128-buf24 invoke MessageBox ,0, ADDR buf128 \ ,ADDR szCaption,MB_OK ;display it invoke RtlZeroMemory ,OFFSET buf24 ,24 ;clear buf24 invoke RtlZeroMemory ,OFFSET buf128,128 ;clear buf128 ret PrintDword endp ;*************************************************** EndCode ***
.code finit fld1 ;A lot of values... fld1 fldz fld1 fld1 fistp dwVl invoke dwtoaInside ,dwVl,ADDR buf24 ;convert dwVal to ASCII ;----> until here the values remaind unchanded invoke MessageBox ,0, ADDR buf24 \ ,ADDR szCaption,MB_OK ;display it ;----> but now, the FPU was cleared!!
I just ran a test, I loaded four values onto the FPU. Stored one and displayed it with dwtoa in an edit box. Got the correct value. Repeated for second, Again correct value Displayed a message box Repeated for third value, still correct and again for fourth, again no problem. So as far as I can tell dwtoa and MessageBox have no affect. Plus reading the dwtoa code reveals it doesn't touch the FPU. Once again I blame wsprintfA One thing though, I no longer trust the FPU. If code works it always works, but sometime I find all values being wiped when I load on a new value. The only way to solve this is to do a different calculation then try to load the value, not always convient at all.
There are event-handlers running in Windows all the time. I hope these, at least, save the copro. But maybe not. Would the LOCK prefix be any help?
Intresting.... I cant imagine why such windows functions would need to touch the FPU at all. The following should work if nesscery, if not then it is the FPU that is buggy: finit fld1 fld1 fistp dword_tmp1 fistp dword_tmp2 invoke PrintDword ,dword_tmp1 invoke PrintDword ,dword_tmp1 Another thing to think about, is maybe an interupt is triggered during the MessageBox call, and another proceedure manages to change the FPU stack or control words.