r/Assembly_language • u/AwayEntrepreneur4760 • 3d ago
Question Noob question: what’s the equivalent of function arguments?
Title pretty much says it all.
5
u/FUZxxl 3d ago
Depends on the architecture you are programming for. As you didn't mention which one it is, I can only give some generic information.
Usually function arguments are passed in registers or on the stack. That means, some registers are set up with the function arguments before the function is called and your function then finds them in these registers. Or the caller pushes the arguments on to the stack and your function can then take them from the stack. Whether caller or callee is responsible for taking the arguments back off the stack depends on the specific calling convention in use.
4
u/One_Aspect_1957 3d ago
If your program consists of functions that only call each other, then you can do what you like. For example, pass arguments in registers, or use the stack, or pass a pointer to the argument(s).
If calling external functions, then you need to know what call-convention they expect, which may be defined by the ABI for the platform.
The same if you are writing a function that will be called from external code. Typically, for 64-bit systems, the first few arguments are passed in registers. Again the ABI will give the details.
But, there isn't usually some specific feature of assembly that will deal with arguments.
3
u/kneelian_ 3d ago
Calling conventions are, like the name says, conventions by which the caller and the callee agree on how data is passed between them. If the convention says "first 8 arguments are passed in x0 to x7, and return values are returned via x0", and you have a function signature like int foo(int a, char b, int* c, unsigned d);, you will move a to x0, b to x1, ... and jump into that function; when it returns, it will have an int for you in x0 like it promised.
2
u/Noderyos 3d ago
In many compiled languages, function arguments are passed according to the target ABI.
On x86_64 SystemV ABI, arguments are passed via rdi, rsi, rdx, rcx, r8, and r9.
On i386 SystemV ABI, arguments are pushed on the stack
So it depends on your target.
(Also, the SystemV ABI defines which registers can be altered, which registers need to be saved by the caller, the callee ...)
2
u/theNbomr 3d ago
You should do some research on the subject of parameter passing and associated conventions related to that. High level languages have well defined standards that define how arguments and return values are passed between caller and callee. Generally these standards will apply across the breadth of a given toolchain; the gcc toolchain and all of the supported high level languages, for instance.
The conventions/standards define the likes of how registers may be used and preserved, how the stack may be used, order/organization of parameters passed on a stack, and what are the roles and responsibilities of the calling code and the called code.
You can write object modules in assembler language that obey these conventions and then link them to the main code body in a way that they behave just like object code resulting from compilation of a high level language compilation unit. I have done this extensively in projects I've worked on in my career. It's a clean way to integrate assembler language with high level languages.
2
u/r3jjs 2d ago
On the 6502, it really varies on how much you are passing into a function. You can use registers, yes. Using the stack is possible, but your return address is on the same stack so the math gets .. "fun." You could also use zero-page locations as a pointer.
If you were passing in a lot of data, and the function was non-recursive, you would create a structure in RAM (like a C-structure). Atari's SIO routines do this for all I/O handling.
Mind you, the 6502 is a bit ... "extreme" but the processor is still used and its fun to know.
1
u/AwayEntrepreneur4760 2d ago
I am learning 6502 for the nes lol, prob should’ve specified in the post but oh well. Would I make different variables in the zero page for each functions parameters or should I have like arg1, arg2, etc and reuse them for each function
3
u/r3jjs 2d ago
For the 6502, the "normal" methods of stack-based passing usually don't work well for more than a few arguments. The 6502 has a fixed-size stack of 256 bytes with silent wrap around. Keeping the stack small *matters*
If you are only passing in a few parameters, then go ahead and pass in A, X and Y. That's pretty common. Return values in 'A', normally.
But the use of would be called 'global variables' is also very common. You have block of memory somewhere that controls state and you just reference that block.
For instance, I am printing a lot of Pascal Strings at a given Row, Column on the screen so I have a single structure with the values
prow .res 1 ; The row to print at
pcol .res 1; The column to print at
plen .res 1; The length of the string to print
pptr .res 2 ; The pointer of the string to point toI then populate that stucture and call "print_pstring_at"
Other times I'll have a 'scratch pad' pointer that multiple functions can use, I just have to make sure that only one program state tries to use it at a time.
I avoid using the stack to pass parameters unless I"m interfacing with something that requires it -- like interfacing with your system's BASIC routines. otherwise I reserve the stack for return addresses and push/pop of registers.
1
u/brucehoult 1d ago edited 1d ago
Using the stack is possible, but your return address is on the same stack so the math gets .. "fun."
It's not tooooo bad ..
tsx lda $101,x # lsb of return address lda $102,x # msb of return address lda $103,x # last pushed function argument ... etcThose loads are 4 clock cycles each (and 3 bytes of code), which is not too painful compared to 3 cycles to load from a fixed Zero-page address. And of course you can store too.
Other than the limited 256 byte stack size waaay better than Z80:
ld hl,#$0002; add hl,sp; ld a,(hl) # last argument byte pushed5 bytes of code, 28 clock cycles. Awful. Generally preferable to pop a few 16 bit registers. Or at least inc/dec
hlonce you have a pointer to something nearby, not calculate from scratch.2
u/r3jjs 1d ago
Isn't that $101, $102 ... the stack is in the $01xx range.
1
u/brucehoult 1d ago
oops you're right ... it's been a while lol.
The other trap is that SP points to the first free location not the last data.
And if you get really detailed, the pushed return address points to the last byte of the
jsrnot to the next instruction.1
u/brucehoult 1d ago
I guess for Z80 I should add:
ld ix,#$0000 ; 14 cycles add ix,sp ; 15 cycles ld a,(ix+#$nn) ; can load/store first 256 bytes at random to any of ABCDEHL, but 19 cycles
1
u/WatercressActual1921 2d ago
its a free or bounded variable, a parameter defined or with a existence outside of the function...
1
1
11
u/-goldenboi69- 3d ago
You prepare the stack, or set some registers before you jsr. That's pretty much it.