dmg@ssc-vax.UUCP (David Geary) (09/18/88)
Sorry if this is a repost; I thought that I'd posted it once, but apparently it didn't get posted: I'm trying to get a grasp on what actually goes on under the covers when passing arguments in C. Here's how I understand the process, please feel free to correct me if I'm wrong: Let's say we have the following: DoIt(x,y,z) int x,y,z; { /* Does something... */ } main() { int a=2, b=3, c=4; DoIt(a,b,c); } Simple enough? ;-) Anyway, here goes... When main() calls DoIt(), the values of a,b, and c are loaded on a stack somewhere in memory. However, as I understand it, the top of the stack is at a higher address than the bottom. Here's what I mean: 1) Load a on the stack (args are loaded left to right, correct?) ADDRESS VALUE 106000 2 2) Then b is pushed on the stack: ADDRESS VALUE 105996 2 106000 3 3) Then c is pushed on the stack: ADDRESS VALUE 105992 2 105996 3 106000 4 Notice that the stack's "top" is at location 106000. In other words the stack grows toward the top of memory. Also, of course, the ADDRESS locations were made up off the top of my head. I am also assuming, for the sake of example, that int's take up 4 bytes in memory. Then, I guess, the address of the calling routine is loaded onto the stack, so that we know where to return when DoIt() is done. So, the stack looks like so when everything is pushed on: ADDRESS VALUE 105988 Address of main() (assuming 4 bytes for pointers, too) 105992 2 105996 3 106000 4 So, this should be the condition the stack is in when DoIt() takes over. When DoIt() takes over, it only knows where the stack starts in memory, and then uses that starting address and offsets to access the x,y, and z in DoIt(). Am I thinking correctly? I've never written a compiler, so I am not real sure about this. Also, I'm a bit confused about what is left up to the compiler as far as HOW to implement the passing of variable values. Does the compiler HAVE TO do it this way. Does the compiler have the freedom to, say, grow the stack towards the end of memory instead of the beginning? Where is all this kind of stuff spelled out? I am teaching an Advanced C course, and am showing my students how to write variadic functions. I want to make sure that the above is correct, and also be prepared to answer the questions in the above paragraph. Thanx for the help, -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ David Geary, Boeing Aerospace, ~ ~ #define Seattle RAIN ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
davidsen@steinmetz.ge.com (William E. Davidsen Jr) (09/20/88)
In article <2235@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: [ discussion about how one C implementation works ] | Am I thinking correctly? I've never written a compiler, so I am not real | sure about this. Also, I'm a bit confused about what is left up to the | compiler as far as HOW to implement the passing of variable values. Does | the compiler HAVE TO do it this way. Does the compiler have the freedom | to, say, grow the stack towards the end of memory instead of the beginning? | Where is all this kind of stuff spelled out? There is no reason why the compiler even has to use a stack at all. It's the common way to do it, but some machines have features which make it inpractical. The VAX has hardware support for other argument passing mechanisms by pointing the argument pointer to a data block. The Honeywell machines don't have a hardware stack, and can have any number of software stacks. | I am teaching an Advanced C course, and am showing my students how | to write variadic functions. I want to make sure that the above is | correct, and also be prepared to answer the questions in the above | paragraph. I hope you're not teaching anything other than varargs... unless they're writing the varargs package for your C implementation you should be doing things the portable way. I've been teaching C since V7, and although I use the stack model as a conceptual model, I repeat many times that it doesn't have to work that way, and that you can't assume it does. -- bill davidsen (wedu@ge-crd.arpa) {uunet | philabs}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me
swilson%thetone@Sun.COM (Scott Wilson) (09/21/88)
>The >Honeywell machines don't have a hardware stack, and can have any number >of software stacks. Can someone explain to me what the difference is between a hardware stack and a software stack? I worked on a C compiler project once where one person said the target machine "doesn't even have a hardware stack." I asked what the difference was between the target machine and, say, a 68000. The answer was the 68000 had a stack because it supported addressing modes like "movl d7,@sp-" whereas the target machine required you to use two instructions, first a move then an explicit decrement of the stack pointer. So what?, I thought. So which machines have a hardware stack and which don't and how do the differences appear to, say, an assembly language programmer. -- Scott Wilson arpa: swilson@sun.com Sun Microsystems uucp: ...!sun!swilson Mt. View, CA
barmar@think.COM (Barry Margolin) (09/22/88)
In article <69210@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes: >Can someone explain to me what the difference is between a hardware stack >and a software stack? A hardware stack is one that has explicit machine instructions and/or addressing modes for manipulating and using a register (or registers) as a stack pointer. Frequently there is a dedicated register for this purpose, and it is used implicitly by some of these instructions. The example you gave was good. If you can push or pop a value on a stack in one instruction, rather than having to increment the stack pointer in a separate instruction, you have the rudiments of a hardware stack (of course, autoincrementing is also useful for stepping through an array). Other operations sometimes supplied with a hardware stack are special call and return instructions that automatically manipulate the stack. For example, if the return instruction knows that the saved PC is at a particular offset from the stack pointer register and automatically pops it into the PC and unwinds the stack, that is a hardware stack. The Honeywell hardware that Multics runs on doesn't have a hardware stack, but there are conventions that a particular register was always used as the stack pointer. The assembler has a RETURN pseudo-op that is actually a built-in macro that does all the stack manipulation for returning (actually, it transfers to a standard shared routine that does the work). Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
will.summers@p6.f18.n114.z1.fidonet.org (will summers) (09/22/88)
In message <69210@sun.uucp> swilson%thetone@Sun.COM (Scott Wilson) writes: > > Can someone explain to me what the difference is between a hardware stack > and a software stack? I worked on a C compiler project once where > one person said the target machine "doesn't even have a hardware stack." > I asked what the difference was between the target machine and, say, a > 68000. > The answer was the 68000 had a stack because it supported addressing modes > like "movl d7,@sp-" whereas the target machine required you to use two > instructions, first a move then an explicit decrement of the stack pointer. Interesting point. Methinks a "proper" distinction would place any stack implemented in the store in the software category. Some kind of on-chip or auxilliary-chip stack would seem to me to be necessary to qualify as a "hardware" stack. A possible exception would be an implementation where the stack storage had a completely separate address space. It's semantics, but seems to me that for a distinction there should be a difference, and one vs. two instructions seems too narrow a difference... \/\/ill -- St. Joseph's Hospital/Medical Center - Usenet <=> FidoNet Gateway Uucp: ...{gatech,ames,rutgers}!ncar!noao!asuvax!stjhmc!18.6!will.summers
cramer@optilink.UUCP (Clayton Cramer) (09/28/88)
In article <69210@sun.uucp>, swilson%thetone@Sun.COM (Scott Wilson) writes: > Can someone explain to me what the difference is between a hardware stack > and a software stack? I worked on a C compiler project once where > one person said the target machine "doesn't even have a hardware stack." > I asked what the difference was between the target machine and, say, a 68000. > The answer was the 68000 had a stack because it supported addressing modes > like "movl d7,@sp-" whereas the target machine required you to use two > instructions, first a move then an explicit decrement of the stack pointer. > So what?, I thought. So which machines have a hardware stack and which > don't and how do the differences appear to, say, an assembly language > programmer. > > -- > Scott Wilson arpa: swilson@sun.com This may be going further back into prehistory than you intended, but I worked on a machine called the Univac 1219 that had no concept of a "stack pointer". Subroutine calls were implemented with an instruction called "B7IJ", which took the current return address and stuffed it into the word at the beginning of the subroutine you were calling. When your subroutine was complete, you executed a return by doing an indirect jump through the address in the first word of the subroutine. Needless to say, there was no way to do recursion without tremendous effort. An example of a machine with a nearly useless hardware stack is the 6502. The stack pointer is an 8-bit register, and the first eight bits of the hardware stack pointer address are optionally definable by a jumper. As a consequence, the hardware stack is only 256 bytes long. If you want to do anything more complicated than a simple video game, or perhaps a simple process control system, plan on building your own stack manipulation subroutines. And you thought the 8086 family was primitive! -- Clayton E. Cramer ..!ames!pyramid!kontron!optilin!cramer
pjh@mccc.UUCP (Pete Holsberg) (09/30/88)
In article <510@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:
...An example of a machine with a nearly useless hardware stack is the 6502.
...The stack pointer is an 8-bit register, and the first eight bits of the
...hardware stack pointer address are optionally definable by a jumper.
...As a consequence, the hardware stack is only 256 bytes long. If you
...want to do anything more complicated than a simple video game, or perhaps
...a simple process control system, plan on building your own stack
...manipulation subroutines.
Yas, and for Gawd's sakes, don't even think about designing a personal
computer around it!! ;-)
Pete Holsberg UUCP: {...!rutgers!}princeton!mccc!pjh
Technology Division ...!att!jonlab!mccc!pjh
Mercer College CompuServe: 70240,334
1200 Old Trenton Road GEnie: PJHOLSBERG
Trenton, NJ 08690 Voice: 1-609-586-4800
dharvey@wsccs.UUCP (David Harvey) (10/03/88)
In article <705.2339B3D8@stjhmc.fidonet.org>, will.summers@p6.f18.n114.z1.fidonet.org (will summers) writes: <body of his message removed> > In message <69210@sun.uucp> swilson%thetone@Sun.COM (Scott Wilson) writes: > > > > Can someone explain to me what the difference is between a hardware stack > > and a software stack? I worked on a C compiler project once where > > one person said the target machine "doesn't even have a hardware stack." > > I asked what the difference was between the target machine and, say, a > > 68000. > > The answer was the 68000 had a stack because it supported addressing modes > > like "movl d7,@sp-" whereas the target machine required you to use two > > instructions, first a move then an explicit decrement of the stack pointer. It seems to me that any register based hardware with register indirect mode and, post-increment and pre-decrement instructions will do the trick for you. Using the 68000 as an example: MOVE.L #$6000,-(A7) ; to push it on the stack MOVE.L (A7)+,D5 ; to pop it back off. This of course creates a normal (goes down in memory as stack grows) stack, but YOU are responsible for where to put the stack. Also, it is highly doubtful that some of the compiler vendors are going to implement it as a stack (they might if that is all they have). That of course means that you will very likely be using Assembler. My bet for saying that a machine has a hardware stack is that it has a register so designated with all the trimmings and trappings as described above. It is the addressing mode that is most important here however, not a designated hardware register as a stack pointer per-se. dharvey@wsccs I am responsible for Nobody and Nobody is responsible for me. The only thing you can know for sure is that you can't know anything for sure.
wes@obie.UUCP (Barnacle Wes) (10/06/88)
In message <69210@sun.uucp> swilson%thetone@Sun.COM (Scott Wilson) writes: | Can someone explain to me what the difference is between a hardware stack | and a software stack? I worked on a C compiler project once where | one person said the target machine "doesn't even have a hardware stack." | I asked what the difference was between the target machine and, say, a | 68000. | The answer was the 68000 had a stack because it supported addressing modes | like "movl d7,@sp-" whereas the target machine required you to use two | instructions, first a move then an explicit decrement of the stack pointer. In article <699@wsccs.UUCP>, dharvey@wsccs.UUCP (David Harvey) replies: > It seems to me that any register based hardware with register indirect > mode and, post-increment and pre-decrement instructions will do the > trick for you. [...] But what about hardware without pre-decrement and post-increment addressing? The Univac 1100 and many derivatives of it, for example. Or the IBM 360 family? With the 360, you usually end up using a register for the stack pointer, and using macros like (forgive me if the syntax is wrong, it has been quite a few years since I wrote a BAL program :-) POP MACRO a MOV (R5),a ADD #4,R5 ENDM PUSH MACRO a SUB #4,R5 MOV a,(R5) ENDM The problem with these macros is that they are not atomic. I can't think of any straightforward reasons why this is a problem, but I'm sure it would cause problems somewhere, somehow. -- {hpda, uwmcsd1}!sp7040!obie!wes "How do you make the boat go when there's no wind?" -- Me --
henry@utzoo.uucp (Henry Spencer) (10/10/88)
In article <202@obie.UUCP> wes@obie.UUCP (Barnacle Wes) writes: >But what about hardware without pre-decrement and post-increment >addressing? The Univac 1100 and many derivatives of it, for example. >Or the IBM 360 family? With the 360, you usually end up using a >register for the stack pointer, and using macros [for pop and push.] >The problem with these macros is that they are not atomic... What you can do, to avoid this, is to allocate some anonymous temporary variables in the stack frame and use them instead of pushing and popping temporary values. Actually, even the original C compiler, with the pdp11's hardware stack support, used this approach to a small extent: the topmost stack location was always a temporary. (The significance of this on the 11 was that after a function call, one less parameter had to be popped off the stack, which was a major win since most functions have few parameters and the 11 was particularly good at popping two or one (or zero!).) By doing this, you can generally avoid stack-pointer movement except as part of the calling sequence. It does mean that accessing small offsets from the stack pointer or frame pointer needs to be efficient, which can impose some constraints. (For example, if you're not using a separate frame pointer, on the 360 the stack must grow downward, since the 360 has positive offsets only.) -- The meek can have the Earth; | Henry Spencer at U of Toronto Zoology the rest of us have other plans.|uunet!attcan!utzoo!henry henry@zoo.toronto.edu
diamond@csl.sony.JUNET (Norman Diamond) (10/12/88)
In <202@obie.UUCP>, wes@obie.UUCP (Barnacle Wes) writes (almost): > POP MACRO a > L R5,a > LA R5,4(R5) > MEND > PUSH MACRO a > S R5,=F'4' > ST R5,a > MEND > The problem with these macros is that they are not atomic. I can't > think of any straightforward reasons why this is a problem, but I'm > sure it would cause problems somewhere, somehow. No problems should be caused by not being atomic. Real problems are caused when programmers carelessly use machine instructions such as POP a or PUSH a and think that they are atomic. In fact, such instructions are also non-atomic (nearly always if not always) and careless programmers create obscure bugs in multiprocessing systems. -- ------------------------------------------------------------------------------- The above opinions are my own. | Norman Diamond If they're also your opinions, | Sony Computer Science Laboratory, Inc. you're infringing my copyright. | diamond%csl.sony.jp@relay.cs.net