Evgenios1 Δημοσ. 21 Οκτωβρίου 2009 Δημοσ. 21 Οκτωβρίου 2009 Μια απλη απορια. Για ποιο λογο να μην γραψουμε ενα προγραμμα το οποιο θα ειναι απο __stdcall και οχι απο __cdecl ? Απο το παρακατω βλεπω οτι το γρηγοροτερο ειναι το standar call. Υγ: διαβασα οτι το esp esi τσεκαρουν κατι... αλλα δε βρηκα τι > FastCall(1); 0041371E mov ecx,1 00413723 call FastCall (411190h) defaultCall(1); 00413728 push 1 0041372A call defaultCall (4110D2h) 0041372F add esp,4 stdCall(1); 00413732 push 1 00413734 call stdCall (4111B3h)
Directx Δημοσ. 21 Οκτωβρίου 2009 Δημοσ. 21 Οκτωβρίου 2009 http://whatilearned2day.wordpress.com/2007/04/13/__cdecl-and-__stdcall/
Evgenios1 Δημοσ. 22 Οκτωβρίου 2009 Μέλος Δημοσ. 22 Οκτωβρίου 2009 Θελω να πω γιατι το default ειναι __cdecl και οχι __stdcall ή καλυτερα __fastcall
bxenos Δημοσ. 22 Οκτωβρίου 2009 Δημοσ. 22 Οκτωβρίου 2009 το stdcall ήταν απο την pascal οπου δεν υπήρχαν var_arg (μεταβλητός αριθμός παραμέτρων). Το cdecl λύνει αυτό ακριβώς (και μόνο αυτό) το πρόβλημα και έτσι έχουμε τη δυνατότητα των var_args. Το μόνο μειονέκτημα του cdecl είναι η επιβάρυνση κάποιων εντολών για cleanup stack μετά απο κάθε call συνάρτησεις (τρίχες δηλαδή!) ή καλυτερα __fastcallτην κολοκυθιά θα παίζουμε;
Evgenios1 Δημοσ. 22 Οκτωβρίου 2009 Μέλος Δημοσ. 22 Οκτωβρίου 2009 lol. Σιγα τις πολλες συναρτησεις..... Μονο δυο ξερω (scanf,printf)
kagelos Δημοσ. 23 Οκτωβρίου 2009 Δημοσ. 23 Οκτωβρίου 2009 το stdcall ήταν απο την pascal οπου δεν υπήρχαν var_arg (μεταβλητός αριθμός παραμέτρων). Το cdecl λύνει αυτό ακριβώς (και μόνο αυτό) το πρόβλημα και έτσι έχουμε τη δυνατότητα των var_args. Το μόνο μειονέκτημα του cdecl είναι η επιβάρυνση κάποιων εντολών για cleanup stack μετά απο κάθε call συνάρτησεις (τρίχες δηλαδή!) την κολοκυθιά θα παίζουμε; Δεν έχει σχέση το stdcall και το cdecl mε var_arg. Η (κύρια) διαφορά τους είναι ποιος καθαρίζει την στοίβα αφού εκτελεστεί η συνάρτηση. Στο stdcall την στοίβα καθαρίζει η κληθείσα συνάρτηση ενώ σε cdecl η καλούσα. Τελικά η ίδια εντολή τρέχει (αυξάνατε ο stack pointer - esp : είπαμε η στοίβα μεγαλώνει προς τις μικρές διευθύνσεις) Επίσης το fastcall έχει αρκετή διαφορά σε ταχύτητα αφού ελαττώνει κατά το δυνατό την πρόσβαση στη μνήμη για τις παραμέτρους, αν και οι υλοποιήσεις διαφέρουν. Αυτό γίνεται γιατί όσες παράμετροι μπορούν, αντί να γίνουν push στην στοίβα, μπαίνουν σε registers. Οπότε εκτός ότι γλιτώνεις την ανάγνωση / εγγραφή στη RAM, γλιτώνεις (σε κάποιες περιπτώσεις) και τις εγγραφές-διαγραφές στην στοίβα. Εν ολίγοις το πιο γρήγορο και πιο ασύμβατο είναι το fastcall (δεν υπάρχει standard για την υλοποίηση). Αυτά περί ταχύτητας εννοείται ότι τα παρατηρείς όταν γίνονται (πάρα) πολλά calls σε μια συνάρτηση και όχι καλώντας την μια και δυο φορές. Ιδιαίτερα με τα σημερινά CPU όπου η συχνότητα του επεξεργαστή σε σχέση με αυτή της RAM διαφέρει τάξεις μεγέθους, μια μικρή συνάρτηση αν χρησιμοποιεί μόνο registers για την εκτέλεση θα εκτελείται δεκάδες φορές πιο γρήγορα.
bxenos Δημοσ. 23 Οκτωβρίου 2009 Δημοσ. 23 Οκτωβρίου 2009 Δεν έχει σχέση το stdcall και το cdecl mε var_arg. Η (κύρια) http://msdn.microsoft.com/en-us/library/zxk0tw93(VS.71).aspx http://msdn.microsoft.com/en-us/library/zkwh89ks(VS.71).aspx The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions αν δεν έχει σχέση, τότε κάνε stdcall με συναρτηση var_arg και να δουμε τι general protection fault θα πάρεις. Δηλαδή η συνάρτηση με stdcall θα ξέρει τι να βγάλει απο το stack; αν δεν υπήρχαν τα var_args θα είχαν ασχοληθεί να φτιάξουν το cdecl; Γιατί, για να ξαναεφευρουν τον τροχό; ------- Τα fastcall όπως και τα register variables, είναι πρόταση προς τον compiler που αν θέλει και μπορεί την χρησιμοποιεί. Γι'αυτο δεν επεκτάθηκα στο θέμα αν θα μπορούσαν να γίνουν standard.
kagelos Δημοσ. 23 Οκτωβρίου 2009 Δημοσ. 23 Οκτωβρίου 2009 Ομολογώ πως δεν το ήξερα. Τώρα που το ξανασκέφτομαι βλέπω την διαφορά. Ο κώδικας της κάθε συνάρτησης δεν μπορεί να αλλάζει άρα πρέπει ο caller να καθαρίζει τον μεταβλητό αριθμό push που έκανε πριν καλέσει την συνάρτηση. Έχεις δίκιο. Βιάστηκα να το πω γιατί θεωρούσα πως ήταν απλά ένα array, αλλά αυτό δεν γίνεται γιατί δεν δηλώνεις (αναγκαστικά) τις μεταβλητές με την σειρά που θα τις περάσεις παράμετρο.
bxenos Δημοσ. 23 Οκτωβρίου 2009 Δημοσ. 23 Οκτωβρίου 2009 και σ'αυτό που είπε ο Ευγένιος για τις printf/scanf ... μπορεί τωρα να είναι λίγες οι va_arg συναρτησεις, αλλα στην εποχη των K&R ήταν ΟΛΕΣ οι συναρτησεις "έτσι". Τότε δεν χρειαζόταν να τις δηλώσεις πριν τις καλέσεις, οπότε ο compiler δεν ήξερε όταν τις καλούσε πόσα arguments θέλαν και αν ηταν τυχερός ο προγραμματιστής και θυμόταν το σωστό αριθμό απο arguments είχε καλώς, αλλιως μπορεί να έπερνε και σαβούρες η συνάρτηση. Αλλά τουλάχιστον δεν θα κατέστρεφε τον stack pointer. Τότε δημιουργήθηκε η ανάγκη για να διαγράφει ο caller τις παραμέτρους απο το stack. πάντως είναι απο τις πληροφορίες που δεν χάνεις και πολλά αν δεν τις ξέρεις
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.