flat assembler
Message board for the users of flat assembler.
Index
> Main > without macro's? Goto page 1, 2 Next |
Author |
|
Mac2004 04 Apr 2009, 03:57
bitshifter: If I understood your question correctly, you can pass arguments
through registers like this: Code: mov eax,1 ;X coordinate mov ebx, 2 ;Y coordinate mov ecx, 100 ;length mov edx, 2000 ;color call MyProcedure There are some other methods as well. regards, mac2004 |
|||
04 Apr 2009, 03:57 |
|
LocoDelAssembly 04 Apr 2009, 04:17
If you want the preprocessor out of this you can still make it somewhat readable. Here an example:
Code: uint32_add: virtual at ebp-.local.size ; Using dot at the beginning of every symbol to make them local to the function .dummyByte db ? ; [EBP-5] .dummy dd ? ; [EBP-4] .local.size = $ - $$ .oldEBP dd ? ; [EBP] .retAddr dd ? ; [EBP+4] .a dd ? ; [EBP+8] .b dd ? ; [EBP+12] end virtual ; Prologue push ebp mov ebp, esp sub esp, (.local.size + 3) and -4 ; User code mov edx, [.dummy] mov cl, [.dummyByte] mov eax, [.a] add eax, [.b] ; Epilogue leave retn 8 uint32_add_end: ; Closing local scope PS: Note that the proc macro does this in a different way so for instance locals and parameters are never available outside while with this method you could still access them (uint32_add.dummyByte for example). Last edited by LocoDelAssembly on 04 Apr 2009, 04:28; edited 1 time in total |
|||
04 Apr 2009, 04:17 |
|
bitshifter 04 Apr 2009, 04:27
Hmm, very interesting.
But does my version look safe to use? Or would it just blow up in my face... |
|||
04 Apr 2009, 04:27 |
|
LocoDelAssembly 04 Apr 2009, 04:34
Your code is correct. If you prefer to do it by hand then you could still go even further and not use an EBP-based frame on leaf functions (like your example). Not sure what is the proper advice for non-leaf functions though, for code safety and debugging I think EBP-based is preferred, but for speed I'm not sure.
|
|||
04 Apr 2009, 04:34 |
|
bitshifter 04 Apr 2009, 04:42
You mean not to use ebp for stack when stack not used inside function?
(I included a local variable in my example only for practice, it does nothing.) Like this? Code: uint32_add: mov eax,[esp+8] add eax,[esp+12] retn 8 |
|||
04 Apr 2009, 04:42 |
|
LocoDelAssembly 04 Apr 2009, 04:48
You could discard EBP even in cases where you have local variables.
Code: uint32_add: sub esp, 8 ; Reserving 7 bytes but aligned to 4 mov edx, [esp+4] mov dx, [esp+2] mov dl, [esp+1] mov eax, [esp+4+8] add eax, [esp+8+8] add esp, 8 retn 8 |
|||
04 Apr 2009, 04:48 |
|
manfred 04 Apr 2009, 14:29
But using locals without setting stack frame makes code bit unreadable...
_________________ Sorry for my English... |
|||
04 Apr 2009, 14:29 |
|
vid 05 Apr 2009, 10:10
In all optimized 64-bit code I saw, compilers tend to drop RBP based frame completely and only use RSP frame. It is caused by the nature of fastcall64 convention to some extent, but same can be easily done for 32 bit code just as well, without any danger or whatever. It is just a bit harder to implement, and you can't debug such code very well.
|
|||
05 Apr 2009, 10:10 |
|
LocoDelAssembly 05 Apr 2009, 22:37
Well on 64-bit world perhaps the choice is easy because you don't code for a 80486 or a Pentium old series processors, but on 32-bit land what happens on situations like this?
Code: sub esp, 64 ; 64 bytes of local variables (just an example) push ebx ; ... .loop: push dword [esp+64+4+4*1] ; Caller's first argument; Callee's second argument push dword [esp+4*2] ; Caller's local variable; Callee's first argument call stdcall_function lea eax, [esp] push eax call another_function_that_modifies_local_var ; ... dec ebx jnz .loop ; ... pop ebx add esp, 64 retn There are no memory address generation stalls there even on PentiumMMX, PentiumII and PentiumIII (and lets count AMD's equivalents too)? |
|||
05 Apr 2009, 22:37 |
|
revolution 06 Apr 2009, 01:42
bitshifter wrote: You mean not to use ebp for stack when stack not used inside function? Code: uint32_add: mov eax,[esp+4] ;+4 to skip the return address on the stack add eax,[esp+8] ;+4 (return address) +4 (to get to the second parameter) retn 8 |
|||
06 Apr 2009, 01:42 |
|
bitshifter 06 Apr 2009, 02:11
revolution:
i am confused, doesnt 'call' push 2 dwords internally? if i push 2 dwords as arguments first, and then 'call' pushes 2 more, shouldnt the first argument be found at at esp+8? |
|||
06 Apr 2009, 02:11 |
|
revolution 06 Apr 2009, 02:17
call pushes EIP, a single 32bit dword, onto the stack.
|
|||
06 Apr 2009, 02:17 |
|
bitshifter 06 Apr 2009, 02:25
ok i get it, my first attempt (at top of page) is implemented correctly but the comments were not correct.
I see the magic 4 byes came from pushing ebp. Thanks for clarifying this situation. (and for putting up with my ignorance) |
|||
06 Apr 2009, 02:25 |
|
LocoDelAssembly 06 Apr 2009, 02:32
Seems that I've corrected your code when I was showing you the ESP-based frame with local vars but forgot to warn you about that
|
|||
06 Apr 2009, 02:32 |
|
bitshifter 06 Apr 2009, 03:00
So the only difference between stdcall and ccall is the retn value?
stdcall: retn sizeof args (removes arguments from stack) ccall: retn nothing (leaves arguments on stack) Last edited by bitshifter on 06 Apr 2009, 03:06; edited 1 time in total |
|||
06 Apr 2009, 03:00 |
|
revolution 06 Apr 2009, 03:05
bitshifter wrote: So the only difference between stdcall and ccall is the retn value? |
|||
06 Apr 2009, 03:05 |
|
bitshifter 06 Apr 2009, 06:32
So if i truly understand this...
Code: ;------------------------------------------------ ; DWORD stdcall uint32_add(DWORD a, DWORD b) ;------------------------------------------------ uint32_add: ; esp -> callers eip ; esp + 4 -> argument a ; esp + 8 -> argument b push ebp ; esp -> saved ebp ; esp + 4 -> callers eip ; esp + 8 -> argument a ; esp + 12 -> argument b mov ebp,esp ; ebp -> saved ebp ; ebp + 4 -> callers eip ; ebp + 8 -> argument a ; ebp + 12 -> argument b sub esp,8 ; make 2 local dwords ; esp -> second local dword ; esp + 4 -> first local dword ; esp + 8 -> saved ebp ; esp + 12 -> callers eip ; esp + 16 -> argument a ; esp + 20 -> argument b ; ebp based access ; mov eax,[ebp+8] add eax,[ebp+12] ; esp based access ; ; mov eax,[esp+16] ; add eax,[esp+20] mov esp,ebp ; esp -> saved ebp pop ebp ; esp -> callers eip retn 8 |
|||
06 Apr 2009, 06:32 |
|
revolution 06 Apr 2009, 06:39
Yes.
|
|||
06 Apr 2009, 06:39 |
|
vid 06 Apr 2009, 08:06
LocoDelAssembly wrote: Well on 64-bit world perhaps the choice is easy because you don't code for a 80486 or a Pentium old series processors, but on 32-bit land what happens on situations like this? ... Your code doesn't exactly reflect way used in funcs with omitted stack frames. You never "push" in such procs. You just reserve enough place on stack for arguments of every function you call, and then you MOVe arguments to stack. So the value of ESP doesn't change over all the procedure. |
|||
06 Apr 2009, 08:06 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.