Sign in to follow this  

which registers do I have to keep intact ?

This topic is 3586 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

I am learning to code asm at the moment to optimize some code. I got most things working but the main thing that I cannot figure out is when to stack which register or flags. Let me give you an example :

; first create data segment, initialized data here
segment .data

; create a string with %s
string_format       db  "%s", 0

; create a segment for putting uninitialized data into
segment .bss

; create a segment for putting you code into
segment .text
	global _ownprintf ; we create a global because we want to acces it form a different place
	extern _printf ; if you want to use a function on the outside use extern
_ownprintf :
	enter 0,0  ; setup the routine

	pusha  ; move all registers to the stack
	pushf  ; move all flags to the stack
	
	push eax
	push string_format
	
	call _printf
	
	pop	ecx 
	pop	ecx

	popf ; get all flag registers back from the stack
	popa ; get all registers back from the stack
	
	mov eax,0
	
	leave 
	
	ret


As you all can see I push ALL the registers to the stack and push all the flags to the stack just in case. Can somebody tell me how to find out which registers/flags I have to push to the stack and which I don't, or point me in the right direction of where to find this info. Thanks Ponl

Share this post


Link to post
Share on other sites
Universal rule: You only need to push/pop the registers that you modify. Only what you do in the current function matters - if you call another function, it will save/restore registers that it uses, so you don't have to worry about that.

Typical convention: You usually don't need to save the Eax, Ecx, Edx or Eflags even if you do modify them. cdecl and (I believe) stdcall calling conventions say that the caller should assume that these are overwritten (these are the two most common calling conventions for C programs and it looks like that's what your function will interact with).

Musts: Ebp, Ebx, Esi and Edi almost always need to be pushed/popped -- but only if you actually use them within your function.

Share this post


Link to post
Share on other sites
So actualy in my last example I shouln't have to call pusha and pushf at all ?
Because I never modified the registers and the calling convention of printf is cdecl.

Thanks for the explanation, please do correct me if the statement above is not correct.

Cheers
Ponl

Share this post


Link to post
Share on other sites
Correct, since Eax and Ecx are the only things you modify, you won't have to pusha or popa.

The 'enter' and 'leave' instructions are optional in your function as well, since you aren't doing anything that needs stack frame setup -- yet.

Also, another "shortcut" for popping after a call is to do this:


Add Esp, 8 ; this will move the stack "down" 8 bytes, as if you popped two 32-bit values.


This way you won't need to pop 'string_format' into Ecx.

This is the typical way that a compiler will clean up after calling a function.


Also any time you want to put 0 into a register, you can xor the register with itself. This results in smaller code and is sometimes faster:


xor eax, eax ; or whatever register you want.



So your final assembly would look like:


push eax
push string_format

call _printf

add esp, 8

xor eax, eax

ret

Share this post


Link to post
Share on other sites
You should prefer manually setting up the stack frame by setting ebp/esp as you want rather than enter/leave - the latter are slow instructions on modern CPUs, since most apps don't use them (compilers generate their own stack manipulation code).

Share this post


Link to post
Share on other sites
@Nypyren : Thanks a lot this helped me much forward.

@Jerax : Could you elaborate on this... How can I enter using ebp and esp? And why would it be faster ?

Thanks!

Ponl

Share this post


Link to post
Share on other sites

This topic is 3586 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this