▲ | kragen 3 days ago | |
Most languages don't have an explicit stack, and even their implicit stack is only for subroutine calls. If you're not making subroutine calls, your compiled code might not access the stack at all. So, for example, here's the strlcpy function from OpenBSD, lightly edited:
GCC 12.2.0 compiles this to the following 18 ARM instructions, with -mcpu=cortex-a53 -Os -S:
If you're not familiar with ARM assembly, I'll tell you that nothing in this entire function uses the stack at all, which is possible because strlcpy doesn't call any other functions (it's a so-called "leaf subroutine", also known as a "leaf function") and because ARM, like most RISCs, puts the subroutine return address in a register (lr) instead of on the stack like amd64, or in the called subroutine like the PDP-8, which doesn't have a stack at all. And the calling convention puts arguments and return values in registers as well. So the function can just move data around between memory and registers and decrement its loop counter and increment its pointers without ever touching the stack.FORTRAN up to FORTRAN 77 didn't support recursion, including indirect recursion, so that you could implement it without a stack. By contrast, in Forth, instead of registers you use the operand stack. For loop counters you use the return stack. Sometimes you can use the operand stack instead of variables as well, although I think it's usually a better idea to use variables, especially when you're starting to learn Forth—it's much easier for beginners to get into trouble by trying too hard to use the stack instead of variables than to get into trouble by trying too hard to use variables instead of the stack. |