jacob navia wrote:
>
>
>>> is it possible using that stack for call of function as
>>> f(a, b)<=> push32 b|push32 a| call32 f
>>
>>
>> Not on my system which doesn't use a stack or have a push instruction.
>>
>
> Ahh OK;
>
>> You shouldn't believe everything you read on Usenet.
>>
>
> You are right. I don't believe you that there isn't (by convention)
> a register pointing to the stack, and that
>
> sub stack,8
> move value,[stack]
>
> doesn't work.
>
> Which system are you using?
I believe ( if I have my Barry's right) that Barry may be working on an IBM
mainframe.
We happen to make C/C++ compilers for the mainframe...
There is no hardware stack (well - technically there is, but it's not very
convenient and isn't used much.... it's a "newer" addition to the hardware
and is a little cumbersome to use and pretty much only stacks the
registers.)
On the IBM mainframe, programs typically do reserve a register to
be the "stack pointer" - they call it the "dynamic save area" (DSA).
Most of the time, this is R13, but that is only by convention.. and many
programmers choose alternatives.
There is no "call" instruction - there is a BALR (Branch and Link Register).
BALR names two registers - the first one receives the address of the
instruction following the BALR, the 2nd one has the branch target.
Thus - to effect a "call", you use BALR to jump to the routine. The
routine
is then obliged to allocate some space and point R13 to it. It can then
save the remaining registers along with the return address (loaded into R14
by the BALR instruction.) You also want to save the previous R13 before
pointing at the new space.
(There is a newer variant of the BALR, named BASR - to handle some
addressing mode situations... newer being, only 20-30 yrs old... BALR
was part of the original specification.)
The "allocation of space" can be as simple as pointing R13 at some static
space in the program; or as complicated as invoking operating system
services to dynamically allocate space, or having the runtime system
manage this space by allocating blocks and giving up chunks of the blocks
as needed.
Then, on return, you load R13 from the saved location (to restore its
previous
value) as well as the other registers... which includes the initial
value of R14.
And, you branch back to the location specified in R14. (You may also have
to de-allocate the space allocated at the start.)
The act of
1) Save R13
2) Point R13 at some new space
...
n) Restore R13 to old value
clearly is a "stack" in the C sense. But, it is interesting to note that
this stack is not contiguous. One stack location doesn't necessarily
have any bearing on another, etc...
This is by convention only - and many mainframe programming
environments decide to abandon that convention... making it rather
frustrating to mix-and-match language implementations or runtime
environments.
So - you are partially right - there is by convention a "stack pointer",
but you can't just subtract a value from it any expect it to work
in any meaningful fashion.
There are aveats here - the newer, post 1990 hardware implemented guard
pages and copy-on-write in the virtual memory addressing system,
so there are new linkage conventions - called XPLINK, that get
close to the subtrace-a-value-from-the-stack-pointer paradigm. But, if the
value you want to subtract is larger than the hardware page size,
then you still have to "punt out" to an out-of-line routine to allocate
stack space and move the guard page...
Also - this all pertains to MVS and z/OS. The z/Linux linkage conventions
follow the z/Linux ELF ABI, where R15 is the stack pointer... and where
things work as you might expect.
- Dave Rivers -
--
Work: (919) 676-0847
Get your mainframe programming tools at
http://www.dignus.com