Skip to main content
GameDev.net gamedev.net
🔒 Locked

Low-level exceptions

Started by RLigon Jun 30, 2004 at 4:31 PM 24 replies 3.3k views
Original Post
RLigon
RLigon
I'm trying to debug some assembly code that I've linked with C/C++ code. I'm using Visual C++ .NET 2002. Does anyone know how to view CPU & coprocessor exceptions? i.e. floating point exceptions? I'm thinking VC++ isn't capable of it. Anyone know of any good tools that can accomplish this? Thanks.
Sneftel
Sneftel
You can use the compiler intrinsic _controlfp or _control87 to set the FPU into exception-signalling mode. They're documented in MSDN.
RLigon
RLigon
anyone know how to watch for other CPU exceptions?
VolkerG
VolkerG
What do you want to do? exceptions are handled by the OS and you can't manipulate the routing at the CPU level. But I doubt that you wan't to be informed about every exception that happens when a page is not in physical memory. Access violation (protecion faults) will be reported by windows anyway.
RLigon
RLigon
I have a vector/matrix library written in assembly that utilizes the Intel SSE instructions. I have a driver program that simply takes two vectors, adds them, and prints out the resulting vector. Here's a snippet:

Vector3 v1 = { 1.0f, 2.0f, 3.0f };
Vector3 v2 = { 1.0f, 1.0f, 1.0f };
Vector3 v3;

// v3 = v1 + v2;
Vec3Add(&v3, &v1, &v2);

// This will print out this: (2.0f, -1.#IND)
printf("(%g, %g)\n", v1.y, v1.y);

Why would it print out 2.0f the first time, but -1.#IND the second time? The same variable (v1.y) is passed twice! I'm very baffled by this one, it's like the stack is being messed up. But I'm almost positive that my Vec3Add function does not corrupt the stack. Any ideas?

VolkerG
VolkerG
Try casting the arguments of printf to a double. WHat compiler are you using (since VC++ casts float to double when using with variable argument lists, as far as I can remember).
printf("(%g, %g)\n", (double)v1.y, (double)v1.y);
hplus0603
hplus0603
In the debug menu, there's an "exception" menu item, which opens a dialog box which lets you specify what to do with each kind of exception.
enum Bool { True, False, FileNotFound };
RLigon
RLigon
I tried typecasting the arguments to printf to doubles. Didn't change anything. I'm using Visual C++ .NET 2002.
RLigon
RLigon
I tried typecasting the arguments to printf to doubles. Didn't change anything. I'm using Visual C++ .NET 2002.
TangentZ
TangentZ
Quote:
Original post by RLigon
But I'm almost positive that my Vec3Add function does not corrupt the stack. Any ideas?


"When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth."

-- Sherlock Holmes

How about showing the code for Vec3Add? [looksaround]
神はサイコロを振らない!
VolkerG
VolkerG
Did you step over the lines using the debugger? What is the value of the variables brfore and after printf?
And what happens when you use printf("(%g, %g)\n", v1.x, v1.y);?
RLigon
RLigon
Here's the entire Vec3Add function in assembly, if anyone still cares about assembly. Doesn't look like I mess up the stack at all...most of the instruction just do operation on data in coprocessor registers.


PUBLIC Vec3Add
Vec3Add PROC pOut:DWORD, pArg1:DWORD, pArg2:DWORD


; Load first argument into xmm0
mov eax, [pArg1]
movups xmm0, [eax]

; Load second argument into xmm1
mov eax, [pArg2]
movups xmm1, [eax]

; Add the two arguments
addps xmm0, xmm1

; Copy result into pOut
mov eax, [pOut]
movdq2q mm0, xmm0
movq [eax], mm0
movhlps xmm0, xmm0
movdq2q mm0, xmm0
movd [eax+2*SIZE REAL4], mm0

ret
Vec3Add ENDP
DigitalDelusion
DigitalDelusion
This is one of the worst cases of missdirected optimization in a very long time, using intrinsics or just letting the compiler do its job would give better performance than that code and we're talking huge speed boosts here.

If you're doing a function call to add vectors then all hope of getting decent performance flies right out the window, if it also forces you to store the vectors in memory you should proclaim the victim (the program in this case) dead at the scene.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
RLigon
RLigon
the value of v1 does not change after the call to printf. It holds (1.0f, 2.0f, 3.0f).

When i try printf("(%g, %g)", v1.x, v1.y) I get the output:
(1.0f, -1.#IND)

Weird
VolkerG
VolkerG
Ok, so I guess it's a problem with the printf call. Did you look at the assembly instructions created by the compiler for that call?
Two printfs (one for each variable) would give the correct result?
Btw., how does the declaration of Vector3 look like?
RLigon
RLigon
Quote:
Original post by DigitalDelusion
This is one of the worst cases of missdirected optimization in a very long time, using intrinsics or just letting the compiler do its job would give better performance than that code and we're talking huge speed boosts here.

If you're doing a function call to add vectors then all hope of getting decent performance flies right out the window, if it also forces you to store the vectors in memory you should proclaim the victim (the program in this case) dead at the scene.


I haven't tested how fast this is, b/c frankly I don't care. I realize that this is a function that could easily be inlined by the compiler. I simply wrote the function b/c I am trying to familiarize myself with SIMD & SSE instructions. And vector/matrices are perfect applications for utilizing these instructions. But I appreciate you steering the topic off course and making your best attempt to belittle me.
RLigon
RLigon
I tried this:

	printf("(%g, ", v1.y);	printf("%g)\n", v1.y);


It yields the following:

(-1.#IND, 2)
RLigon
RLigon
Vector3 looks like this:

struct Vector3{    float x, y, z;};


I also tried this:

_declspec(align(16)) struct Vector3 ...

which didn't make a difference. (not that I would expect it to really)
DigitalDelusion
DigitalDelusion
Quote:
Original post by RLigon
I haven't tested how fast this is, b/c frankly I don't care. I realize that this is a function that could easily be inlined by the compiler. I simply wrote the function b/c I am trying to familiarize myself with SIMD & SSE instructions. And vector/matrices are perfect applications for utilizing these instructions. But I appreciate you steering the topic off course and making your best attempt to belittle me.


Well SIMD and SSE instructions can be played with using compiler intrinsincs and/or inline assembly instead of using an external assembler. I was merly pointing out some obvius shortcommings of your approach not trying to belittle you but Im honestly sorry if I somehow hurt your precious ego.

And to come back on topic as pointed out by others it seems like your printing doubles and sending floats, as VolkerG said have a look at the generated assembly.
Or why not use %f when you know you're sending floats?
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
RLigon
RLigon
%g doesnt do anything special except it only prints the significant digits of the significand. i.e. 1 instead of 1.00000

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.