flat assembler
Message board for the users of flat assembler.
Index
> Windows > Win32 calls. Register usage? Goto page Previous 1, 2, 3, 4, 5 ... 9, 10, 11 Next |
Author |
|
arigity 08 Jun 2009, 00:41
i didn't really bother reading most of what you guys wrote but from an optimization standpoint cdecl is a considerably better option then what your suggesting.
cdecl Code: push somearg push someotherarg push 35 push omgsjnwet call cdeclfunction add esp, 10h cdeclfunction: push ebp mov ebp, esp mov edi, edi leave retn azdecl Code: push somearg push someotherarg push 35 push omgsjnwet push 14h call azufunction ; this is probably the easiest form of a vararg function which manages its own stack azufunction: push ebp mov ebp, esp mov edi, edi leave pop ecx add esp, [esp] ; arg1 jmp ecx because you (or the compiler) still need to know the number of args to pop off the second calling convention adds no benefit over cdecl while increasing the size of the executable, and it also may noticeably slow down your program as well. also, what you describe (popping them off as you need them) is not actually a calling convention but a programming practice, calling conventions are just the way parameters are passed, who manages stack, and what registers are preserved, also what you wrote it will get increasingly more complex if you need to use an argument in more then one spot, and should an argument be passed but NOT used things get even worse. for example Code: push somearg push someotherarg push 35 push omgsjnwet call azufunction2 ; very small example of what i mean. azufunction2: pop eax test eax, eax je .UnInitialized ; if its NULL we don't pop off those 3 pop ecx pop edx pop eax .UnInitialized: retn p.s. hi |
|||
08 Jun 2009, 00:41 |
|
Azu 08 Jun 2009, 00:46
arigity wrote: i didn't really bother reading most of what you guys wrote but from an optimization standpoint cdecl is a considerably better option then what your suggesting. arigity wrote: also, what you describe (popping them off as you need them) is not actually a calling convention but a programming practice, calling conventions are just the way parameters are passed, who manages stack, and what registers are preserved, also what you wrote it will get increasingly more complex if you need to use an argument in more then one spot, and should an argument be passed but NOT used things get even worse. |
|||
08 Jun 2009, 00:46 |
|
arigity 08 Jun 2009, 00:59
not wrong number of args, just unused args. not all arguments are always used in a function and they are certainly not always used in the same order they are pushed. another (more common) example is this:
Code: proc DllMain hInstance, reason, lpReserved pop eax ; hinst we don't need it so we just trash it pop eax ; reason cmp eax, DLL_PROCESS_ATTACH JNE .next call DllInit jmp .quit .next: cmp eax, DLL_PROCESS_DETACH JNE .quit call DllUnInit .quit: mov eax,TRUE retn endp DllMain DOES take 3 arguments, so its the right number, but i am only interested in the reason so the first gets trashed (unless i want to spare a register or use some local var) and the third is never popped |
|||
08 Jun 2009, 00:59 |
|
Azu 08 Jun 2009, 01:01
arigity wrote: not wrong number of args, just unused args. not all arguments are always used in a function and they are certainly not always used in the same order they are pushed. another (more common) example is this: |
|||
08 Jun 2009, 01:01 |
|
arigity 08 Jun 2009, 01:20
having to ALWAYS use every argument and in the exact order they were pushed when creating functions using that standard is somewhat limiting don't you think? additionally local variables will be considerably more tricky to pull off if all you do to grab the args is 'pop reg'
honestly it would be way to much trouble as your code will most likely be more bulky and slower then using another standard not to mention the others don't have the same limitations. |
|||
08 Jun 2009, 01:20 |
|
Azu 08 Jun 2009, 01:30
arigity wrote: having to ALWAYS use every argument and in the exact order they were pushed when creating functions using that standard is somewhat limiting don't you think? additionally local variables will be considerably more tricky to pull off if all you do to grab the args is 'pop reg' arigity wrote: honestly it would be way to much trouble as your code will most likely be more bulky and slower then using another standard not to mention the others don't have the same limitations. |
|||
08 Jun 2009, 01:30 |
|
arigity 08 Jun 2009, 01:51
Azu wrote: No, there is no reason for it to use them backwards or whatever, that is not how the function works. if you do not pop them off in the right order, you will end up with the wrong argument. if you tried to pop off argument 7 when you have only popped of 3 before, you will have to pop off the other 3 in between before you can get to 7 with how you do it. Azu wrote: The way it is NOW is bulky and slow and bloated.. it would be smaller/faster without the cdecl junk. i do not see how adding a single instruction after a function call can be considered bulky slow and bloated, what you suggest can only ever add more to its size and execution-time because you need to save the arguments *somewhere* if you ever plan to use them again and you need to save where your going to return to *somewhere* (or you will pop it off) and you need to re-do how local variables work (because if all you do to grab arguments is 'pop reg' you will end up popping off ebp) all those modifications to the function should add considerably more then what cdecl tacks on. |
|||
08 Jun 2009, 01:51 |
|
Azu 08 Jun 2009, 02:02
arigity wrote:
arigity wrote:
|
|||
08 Jun 2009, 02:02 |
|
LocoDelAssembly 08 Jun 2009, 02:07
Azu wrote:
The code I provided to you was exactly to prove this wrong. wsprintf tolerates receiving more (but not less) arguments than required per fmt string (and works gracefully, of course). I have provided an Assembly version also in case you can't understand the C version but if you like with If-Else: Code: function void printPerson(Person person) { char *fmt; if (person.showAge) fmt = "Person %u works at %s, and is %u years old"; else fmt = "Person %u works at %s. Age can't be disclosed"; printf(fmt, person.id, person.department, person.age); /* Single point of call for both fmt strings */ return; } |
|||
08 Jun 2009, 02:07 |
|
Azu 08 Jun 2009, 02:12
I don't know the HLL syntax but obviously you should push the right amount of args, like I already said.
|
|||
08 Jun 2009, 02:12 |
|
arigity 08 Jun 2009, 02:43
you only write to the buffer once in wsprintf? you only read from the format once in wsprintf? i'm pretty sure there are more vararg functions then the *printf series.
calling convention: 1. you can't read more then once from an argument 2. you have to have the arguments in the EXACT order they are used 3 you always need to use every argument not to mention the added measurements for correctly returning and local variables. currently wsprintf looks like this in cdecl format *note* push ebp/mov ebp,esp and ending pop ebp removed from both *note* also those numbers at the beginning are how many bytes it have been used Code: 3 lea eax,[arg3] 4 push eax 7 push [arg2] 10 push [arg1] 15 call wvsprintfA 16 retn using your format it might look something like this Code: 6 pop [return_addy] 7 pop eax 8 pop ecx 10 mov edx, esp ; lea arg3... i think. 13 add esp, 4 14 push edx ; lea arg3 15 push ecx ; arg2 16 push eax ; arg1 21 call wvsprintfA 27 push [return_addy] 28 retn |
|||
08 Jun 2009, 02:43 |
|
LocoDelAssembly 08 Jun 2009, 02:44
The calls with person.showAge equal to zero are valid in the code above and in the two codes I have posted earlier. Also, it is supposed to be right doing so, not some kind of safe to protect buggy code.
|
|||
08 Jun 2009, 02:44 |
|
Azu 08 Jun 2009, 02:49
arigity wrote: you only write to the buffer once in wsprintf? you only read from the format once in wsprintf? i'm pretty sure there are more vararg functions then the *printf series. arigity wrote: calling convention: arigity wrote: 2. you have to have the arguments in the EXACT order they are used arigity wrote: 3 you always need to use every argument arigity wrote: not to mention the added measurements for correctly returning and local variables. arigity wrote: currently wsprintf looks like this in cdecl format LocoDelAssembly wrote: The calls with person.showAge equal to zero are valid in the code above and in the two codes I have posted earlier. Also, it is supposed to be right doing so, not some kind of safe to protect buggy code. Anyways I've had enough of looking at/talking about this HLL crap.. I feel like it's melting my brain.. back to sweet, sweet assembly for me. Bye |
|||
08 Jun 2009, 02:49 |
|
LocoDelAssembly 08 Jun 2009, 02:59
Quote:
The mess you have seen has nothing to do with the stack pointer adjustments I presume, specially because wvsprintf should return with "ret 12" without doing anything special over other stdcall routines. And about moving the push to the IF body no thanks, I prefer the other way I have implemented in the Assembly code posted earlier which contains no branches (or do you have a way to conditionally push something without branching?). |
|||
08 Jun 2009, 02:59 |
|
Azu 08 Jun 2009, 03:05
Oh, my mistake. It looked like HLL crap to me, and didn't compile in FASM, so I assumed it was HLL crap not assembly. If you're talking assembly, please continue.
|
|||
08 Jun 2009, 03:05 |
|
arigity 08 Jun 2009, 03:20
Azu wrote: Exactly like all of the other Windows functions. several windows functions will not use one or more of its arguments under some circumstances. Azu wrote: It doesn't need to, and doing so would be wasteful. Why read the same thing from main memory multiple times when you are only going to use it once? aside from the fact you only have a few registers to store data in, most non-trivial functions DO use arguments more then once. Azu wrote: You have to put the arguments in the right order the way it is now, too. It can't read your mind. your misunderstanding reading an argument with pushing one. you shouldn't need to read the first two arguments in order to read the third Azu wrote:
whats wrong with how it sets up the stack/returns to the previous function? Azu wrote: Huh? Mine isn't a wrapper function. It's standalone. And in my format it would be much smaller/faster then wvsprintf alone, yet alone wsprintf+wvsprintf.. its meant to show that your convention needlessly tacks on extra things in even the most minimalistic of functions. without doing some major improvements to the function there is no way your way would make it smaller or faster. |
|||
08 Jun 2009, 03:20 |
|
Azu 08 Jun 2009, 03:41
k, like I said, I've had enough of this HLL crap. The limitations in it are nonsensical.
|
|||
08 Jun 2009, 03:41 |
|
pal 08 Jun 2009, 07:20
OK I may make myself look like a complete idiot here; but what is wrong with having an API which takes varargs where the first argument in the API is the number of varargs e.g.
Code: wsprintf(5,"hi %s %i %d %f %x",szString,iInt,iInt,fFloat,lHex); And it can then just do an Code: add esp,arg1*4 Or something before the ret, or a Code: ret arg1*4 |
|||
08 Jun 2009, 07:20 |
|
revolution 08 Jun 2009, 08:02
pal: nothing wrong with that, just that it is not a standard HLL calling standard. In asm you can do whatever you like to calling conventions, no discussion necessary. In HLL, you have to follow the standards.
The original discussion point was that the single WinAPI function that is vararg "should be stdcall also". I think it has been well and truly proven by now that it is not sensible for many reasons. |
|||
08 Jun 2009, 08:02 |
|
Goto page Previous 1, 2, 3, 4, 5 ... 9, 10, 11 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.