Hello all the experts here, I would like to know how a typical porcessor executes a function call or subroutine call in a assembly code.
I know it uses stack for doing it and I do understand the mechanism about the stack here. I would want to go one step further and ask you how it exaclty saves the internal variable, returned variable and call in functions and all those things. If you see I am asking something like a compiler design, where in it maps the high-level language into architecture specific assembly code. I would really appreciate if you could do with an example.
I propose something like this,
main {
int k = foo (int a, int b, int c); foo uses lets says 5 local varaibles.
where in foo calls another function int l = foo1 (int d, int e); foo1 uses 2 local variables.
snipped-for-privacy@gmail.com wrote in news:1108112842.485983.209510 @o13g2000cwo.googlegroups.com:
Well, to give Microchip's PIC micro-controller as an example. It only has one working register (W). I have not used any other chips, but I know Intel chips in your home PC have many more.
I'd use the W register for the return value. But Id need to tell my assembler in advance that I wanted to use a,b and c. Because I have not OS that can dynamically allocate memory for me.
So for int k = foo (int a, int b, int c);
I would globally define a, b, c Set some values in a,b,c Call the foo function
Foo: Movlw a,w Addwf b,w Addwf c,w Return
And end up with the result in the W register.
The stack is used by the processor to remember program jumps, because the location of Foo in program memory is way off in some distant place. But I never worry about this.
The only time the Stack is of concern for me is in implementing recursive functions, because the stack is only so deep and could overflow.
It's good that you know C but you will quickly answer any questions you have about the low level stuff, if you looked at a datasheet of any micro-controller or processor.
Here is a simple one
formatting link
DaveC
----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
formatting link
The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
This is not necessarily true. Using the stack is theoretically what you'd like to do because it makes the function calls re-entrant. However the crippled architecture of small micros (and possibly issues with caching with larger ones) make it sometimes necessary to just use part of memory of some kind for the required storage.
Yes, it's pretty much that.
Okay, it's a little more complex than that because there will be registers that have to be saved in addition to the automatic variables in foo/foo1. At least the accumulator(s), but maybe some floating point registers etc. The compiler will hopefully figure out the minimum that is required, rather than just saving everything every time (safer from compiler bugs, but potentially very inefficient).
One way is just to push the accumulator(s), index registers etc. on the stack, and assign automatic variables within a stack frame for the function. There might be more than one stack, BTW. Some small processors have a hardware stack for function calls. That creates re-entrant code to the extent you don't run out of stack space.
But in brain-dead small micros with Harvard architecture, often non-re-entrant functions are used- some general purpose (on-chip or off) RAM is allocated for the storage of automatic variables etc. . This is not as elegant.
A von Neuman 8-bit micro such the HC908 might have a compiler that would do something like (generated by Metrowerks CodeWarrior C/C++ cross compiler):
;int foo1(int d, int e) { ; int v,w; ; v = d; w = e; ; return d + e; ;}
Now, here's a similar dissembly listing generated by PIC18 cross-compiler for the PIC18 core-- Quite a difference! This one uses fixed memory locations rather than Push/pull from the stack.
--
"it's the network..." "The Journey is the reward"
speff@interlog.com Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog Info for designers: http://www.speff.com
If you're programming a small micro in C, you'd better understand both.
Best regards, Spehro Pefhany
--
"it's the network..." "The Journey is the reward"
speff@interlog.com Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog Info for designers: http://www.speff.com
In the 8051 it usually depends a great deal on whether the function involved must be able to be re-entered. If not, the linker allocates the variables in memory such that routines that can't be running at the same time reuse locations. Effectively the variable spaces get merged. This is part fo the reason that a good C compiler can make 8051 code that is only 3 times slower than assembly.
Returned values are usually put into ACC or (B,ACC) if they are 16 bit.
80x86 compilers store not only the subroutine return address, but also function parameters and local variables on the stack. Together, they comprise the stack frame. Often, a special register called the base pointer keeps track of where they are. The parameters and variables are accessed using base pointer relative addressing. Here's a (16-bit) stack frame:
BP+6 => Param1 BP+4 => Param2 BP+2 => Return adddress BP+0 => Previous value of BP saved here BP-2 => Local1 BP-4 => Local2
You can read about this in books and on the web, or you can just inspect the code your compiler produces.
If your processor doesn't have base pointer support, then the compiler has to do a lot more work!
This is the sort of question you can best answer by investigation. Google will help you more than the busy people on newsgroups can. You need to get a C compiler and look at the output listing. I recommend Pelles C from :
formatting link
If you target the 80x86 family, you get a beautiful clear assembly you can work through. Unlike many small and RISC processors, the 80x86 family compilers tend to give consistent output for high level languages no matter how many levels deep are your function calls.
Pelles C gives you a nice editor to write and compile from. To see the output listing run the PODUMP utility with the /DISASM switch on the .OBJ files .
@2: [00000026] 5B pop ebx [00000027] 89EC mov esp,ebp [00000029] 5D pop ebp [0000002A] C3 ret
The function call to foo1() pushes on the stack the parameters from in eax and ebx. The ebp is an indexing register used to access the stack variables belonging to a function.
sub esp,+10 makes room for local variables while add esp+8 releases that stack space at the end of the function.
If you start with simple function calls, you can work out what is going on.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.