Archived

This topic is now archived and is closed to further replies.

ASM Problem ("Saving" ESP register problems) (Please help...)

This topic is 5316 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey there. I''m programming a game with my DirectX 3D engine, and I want to optimize it using ASM (Assembly Language). Right now I am trying to call the IDirect3DDevice8::SetRenderState() functions ASM. Here is my code right now:
  
		__asm 
		{
			;; Enable z-buffer parameters
			PUSH 1                              ;; Second parameter
			PUSH D3DRS_ZENABLE                  ;; First parameter

			;; Call the IDirect3DDevice8::SetRenderState function
			MOV  EAX, DWORD PTR g_pDevice       ;; Interface of d3d device
			MOV  ECX, DWORD PTR [EAX]           ;; Move EAX pointer to ECX
			MOV  EDX, DWORD PTR g_pDevice       ;; Set EDX as ''g_pDevice''
			PUSH EDX                            ;; Push out EDX

			CALL DWORD PTR [ECX+200]            ;; Set the z-buffer render state
		}
  
When I run the executable file it gives me an error. It says that the ESP register was saved correctly. I have tried "ADD ESP, (4, 8, 16, 32, and 64)", and they still give me an error. Here is the code that I converted, using Listing Files in the Settings:
  
	mov	eax, DWORD PTR ?g_pDevice@@3PAUIDirect3DDevice8@@A ; g_pDevice
; Line 434
	mov	ecx, DWORD PTR [eax]
; Line 435
	mov	edx, DWORD PTR ?g_pDevice@@3PAUIDirect3DDevice8@@A ; g_pDevice
; Line 436
	push	edx
; Line 438
	call	DWORD PTR [ecx+200]
; Line 440
	add	esp, esi
  
and I have also tried the "ADD ESP, ESI", but sometimes my computer will freeze and I have to restart it. Can someone please give me the correct method for "saving" the ESP register? Thanks in advance! =) If thispost = 0 Then GoBack() Else Read() End If

Share this post


Link to post
Share on other sites
I just tried that, but it gives me the same error. It says ESP wasn''t saved properly across a function call. Also, it says it may be caused by calling a function declared with one calling convention with a function pointer declared with a different calling convention.

Share this post


Link to post
Share on other sites
quote:
Original post by SimDemon
PUSH 1
PUSH D3DRS_ZENABLE
PUSH EDX

When I run the executable file it gives me an error. It says that the ESP register was saved correctly. I have tried "ADD ESP, (4, 8, 16, 32, and 64)", and they still give me an error.


I'd be inclined to think you'd have to 'add ESP, 12', as you're pushing 3 DWORDs.


[edited by - Namethatnobodyelsetook on May 27, 2003 12:20:16 AM]

Share this post


Link to post
Share on other sites
Try a stack frame....


--------------------------------------------------
push ebp ; preserve base pointer
mov ebp, esp ; stack pointer into ebp

; write you own code here.

mov esp, ebp ; restore stack pointer
pop ebp ; restore base pointer

ret
----------------------------------------------------

push esp
blah
pop esp

will not work is esp is modified, because you lost the address where you pushed esp!!!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Why? calling SetRenderState using assembly will be no faster than using C++. Before you start assembly optimizing, take a look at the output assembly of your C++ compiler. If it''s horribly inefficient (usually not) it might be worth it for functions that are called very often.

Share this post


Link to post
Share on other sites
None of those suggestions work either. I am calling more than on SetRenderState() function. No matter what I do it won''t work. I don''t know what is wrong with this. =(

If thispost = 0 Then
GoBack()

Else
Read()
End If

Share this post


Link to post
Share on other sites
there is no reason to do this:

MOV EAX, DWORD PTR g_pDevice ;; Interface of d3d deviceOV
MOV ECX, DWORD PTR [EAX] ;; Move EAX pointer to ECX

it is the same as:

MOV ECX, DWORD PTR [g_pDevice] ;; Move value at pointer to ECX

the only reason to stuff like this usually is to get to a pointer to a pointer. this is what you may want:

MOV EAX, DWORD PTR [g_pDevice] ;; pointer to d3d interface
MOV ECX, DWORD PTR [EAX] ;; Move EAX pointer to ECX

I know how to do this with assem, but I''m currently reinstalling my comp. Thats my best guess atm.

Share this post


Link to post
Share on other sites
I am never going to figure this out. I tried what you suggested, and it gives me the same error. It''s an access violation. When I try to debug, it comes up with disassembly, and just says this:

int 3

If thispost = 0 Then
GoBack()

Else
Read()
End If

Share this post


Link to post
Share on other sites
WHY DO YOU NEED ASM TO MAKE A FUNCTION CALL???

The problem is the calling convention (cdecl) requires the callER to fix ESP. simply subtract from ESP the number of bytes you pushed onto the stack for the paramiters. Check other listings for how this works. I strongly suggest you use C++ for this, there is no benifit of using ASM other then if you are processing huge amounts of data. Even then C++ can be optimized sufficiently

Share this post


Link to post
Share on other sites
quote:
Original post by Namethatnobodyelsetook
I''d be inclined to think you''d have to ''add ESP, 12'', as you''re pushing 3 DWORDs.



Bingo.

quote:
Original post by Cybertron and Anon
WHY?



Bingo, again.

How is hand writing exactly what the compiler is already producing going to be any faster?

If assembly is going to help you with speed, it''s NOT going to be in making function calls. It''s going to be in ELIMINATING function calls and writing hand-tuned replacements for memory copies and the like.

Your time will probably be better spent finding ways to reduce render state changes, better use of vertex/index buffers, etc.

Share this post


Link to post
Share on other sites
The above posts probably have your problem.

If you are using VC, here is some tip to help debug what you are trying to do:

All DX functions setup a stack frame on entry. If you have a call failing, set a breakpoint on the call. The using the disassembly window press f11. If you are calling to the right place, you should see something like the start of a stack frame:

push ebp
mov ebp,esp
.
.
.

If thats is what you are calling to, you have correctly called one of the DX functions.

Then you need to make sure your parameters are correct. If you are having a realy hard time making sure they are correct. Run a second instance of VC and look at the dissassebly for the C++ code.

Your code and the C++ code should both have the same index offest for the call:

call [ecx+(same)]

If it is the same, you know you have the right function. Look at how many parameters are being pushed. Also look at what is being pushed:

push edx
push [edx]

lea eax,[something]
push eax

Are very different. Make sure you have the right level of indirection to pointers in the parameters you push.






Share this post


Link to post
Share on other sites
since we are already talking about ASM here

(i am willing to learn the basics)

is it worth it to use asm to write some piece of code that animates my highpolygonal skeletal animated models?

these vertex/pixel shader codes look a lot like ASM i think so maybe i can gain an advantage of using asm to animate my models?
thx

Share this post


Link to post
Share on other sites