In the assembly, all bets are disabled, and you can pass parameters at your discretion, provided that the caller and the callee agree on how to do this.
Put the arguments on the stack, put a pointer to them on the stack, put them on registers, copy them to a fixed memory location, it all depends on you. I have seen cases where some arguments were passed in registers, while others were passed on the stack or passed by reference.
How you transfer control is also up to you. Execute a call command or software interrupt. The old PDP-10 architecture has five different ways to call a subroutine, and you needed to know which one to use. The IBM 360 architecture also has a number of ways.
(Do you want to see it crazy? Read the famous Interrupt List , which was a collection of all the known software interrupt calls available for 286, almost every part of the software installed in MS-DOS added several new software interrupts to the bank, and each of them had its own their own calling convention, and many of them ran into each other.)
In general, your best approach is to find out what other programmers are doing and do the same. Either this, or document your function very well so that users know what to call it.
Now, if your assembly will call or be called in another language, such as C, C ++, Fortran, etc., you need to study the standard calling conventions that were set by the language developers, and which usually also depend on the architecture. For example, for C on a 32-bit x86, the arguments will be passed on the stack, while for Sparc up to five arguments will be passed to the registers, and everything that came next was on the stack.
As for structures, the C standard requires them to be unpacked and separate elements that must be passed as separate arguments that must be reassembled into the structure by the called one. If the structure is very large, it can be insanely wasteful, so it's best to pass a pointer to the structure.
If a function returns a structure, the caller allocates space to receive it and passes a pointer to this space as the "secret" argument to the function.
Arrays are always passed as pointers.
For Fortran, everything is passed by reference, which means that values ββcan be returned in any argument. Even the constants are hidden in memory somewhere, and a pointer to them is passed to the called routine. (Thus, you can accidentally change the value of a constant.)