From: Shawn Hargreaves Newsgroups: comp.os.msdos.djgpp Subject: Re: Some Asm and C questions. Date: Sat, 8 Feb 1997 15:54:39 +0000 Organization: None Distribution: world Message-ID: References: <32FBBA4C DOT 5582 AT post DOT comstar DOT ru> NNTP-Posting-Host: talula.demon.co.uk MIME-Version: 1.0 Lines: 109 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Dim Zegebart writes: >I have in C code some structure >typedef struct >{ int event; > int param1; > int param2; >} Events; >[snip] >Events EventsQueue[1000]; > >Also I have a function >void PostEvent(int Event,int Param1,int Param2) >{ > [snip] >} > > >And also I have in .s file interupt handler function for com port. >So, my questions: >1. How can I call PostEvent with parameters from asm code? With any question of this sort, the answer is to look at the code output by gcc and copy it. Write a little C prog: void PostEvent(int Event,int Param1,int Param2); void myfunc() { PostEvent(1, 2, 3); } Compile it with 'gcc test.c -S', and you get: _myfunc: pushl %ebp movl %esp,%ebp pushl $3 pushl $2 pushl $1 call _PostEvent addl $12,%esp L1: leave ret So, you push the parameters onto the stack in right-to-left order, call the function (prefixing the C name with an underscore), and then pop the parameters off the stack (three 32 bit integers takes 12 bytes, so you add 12 to esp). In this case you don't actually need to bother repairing esp, because the 'leave' instruction will do that anyway: if you compile the C prog with '-O' you'll find that gcc leaves out the add. A bit more investigation will reveal that return values are passed in eax, and that after you call a C function the contents of eax, ecx, and edx are likely to have changed, but ebx, esi, and edi will be preserved. >2. How can I read and write to EventsQueue fields in asm code? Again, look at what gcc does! Write a C prog: typedef struct { int event; int param1; int param2; } Events; Events EventsQueue[1000]; int EventCounter; void PostEvent(int Event, int Param1, int Param2) { EventsQueue[EventCounter].event = Event; EventsQueue[EventCounter].param1 = Param1; EventsQueue[EventCounter].param2 = Param2; } When you compile this (I used -O, because gcc produced really messy code without it), you'll get a nice little example of exactly what you need to do. The comments are my own additions: gcc isn't quite smart enough to annotate the output yet :-) _PostEvent: pushl %ebp movl %esp,%ebp pushl %esi pushl %ebx movl 8(%ebp),%ecx // load event into ecx movl 12(%ebp),%ebx // load param1 into ebx movl 16(%ebp),%esi // load param2 into esi movl _EventCounter,%eax // load array index into eax leal (%eax,%eax,2),%eax // mul by 3 (3 ints in struct) sall $2,%eax // mul by 4 (4 bytes in an int) movl $_EventsQueue,%edx // load array address into edx movl %ecx,_EventsQueue(%eax) // write event value movl %ebx,4(%edx,%eax) // write param1 4 bytes later movl %esi,8(%edx,%eax) // write param2 8 bytes later leal -8(%ebp),%esp popl %ebx popl %esi leave ret /* * Shawn Hargreaves - shawn AT talula DOT demon DOT co DOT uk - http://www.talula.demon.co.uk/ * Ghoti: 'gh' as in 'enough', 'o' as in 'women', and 'ti' as in 'nation'. */