- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
#include <stdio.h> #include <signal.h> void getStatus() { short status; __asm__( "fnstsw %0\n\t":"=m"(status) ); printf("0x%x\n", status); } void setUnmask() { int cw = 0x366; __asm__( "fldcw %0\n\t"::"m"(cw) ); } /// Get the status register content of X87 FPU. short getExcepFlag() { short status; __asm__( "fnstsw %0\n\t":"=m"(status):"m"(status) ); return status; } int fpu(int value) { int result = -1; for (int i = 0; i < 10; ++i) { __asm__( "fldl %0\n\t":"=m"(result):"m"(value) ); printf("normal\n"); getStatus(); } return result; } void sigHandler(int sig) { printf("Get an exception\n"); long temp; short status = getExcepFlag(); printf("0x%x\n", status); if (status & 0x00C0 == 0x00C0) { if (status & 0x0200 == 0x0200) { __asm__("fnclex\n\t"); __asm__("fstp %0\n\t":"+m"(temp):"m"(temp)); } else { } return; } } int main() { setUnmask(); signal(SIGFPE, sigHandler); fpu(123); }
However, the result was not the same as what I expected.
First, if I did fldl 9 times(change i<10 to i<9), the status word showed there was an exception. (SW was 0x82c3) But my signal handler didn't get a signal and printed nothing.
Second, after fldl was executed 10 times, the sigHandler worked. But the returned value status was always 0x0, it seemed that the SW was cleared. Therefore my handler couldn't determine which was the exception.
Finally, the sigHandler would be executed infinite times. The printing wouldn't stop itself.
I have read D.3.4, Volume 1, Developer's Manual, and found some similar situations. But I am confused about that whether can I deal with the exception with C/C++ and signal(), because the examples are all written in assembly code.
My environment is Ubuntu 17.10.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It would have helped, if you would have commented your code, and explained (to me and other readers) what you had in mind.
It is a bit complicated to debug a mixture of C and inline Assembly, when you know what is wanted.
It is twice as hard, when you must guess what the author had in mind.
Suggestion: write down the state of the internal FPU stack, after each "push" of
__asm__ ( "fldl %0\n\t"
:
"=m"
(result):
"m"
(value)
) ;
![](/skins/images/7FC17B7B85029576C25F1E43CE255B51/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page