Psuedocode illustrating this process with our previous example is shown below (note that push and pop are not real MIPS instructions; this is just for illustration purposes). be stored somewhere. on MIPS, following conventions (with 4 or fewer parameters): The stack gets used for more than just pushing/popping stack frames. This is necessary (even though procB only receives Previously in this sort of situation, you simply would use some arbitrary registers to use here. The 't' in $t stands for temporary. of a $s register implies that there. In the above psuedocode, the intended semantics of push $ra is to push the current value of $ra onto the call stack.

2 parameters). We do not allocate extra space in order to ensure that stack allocations are always in uniform-looking blocks.

The pop $ra instruction in third puts the value on top of the stack into register $ra, resulting in a stack that looks like the following: The next instruction executed is third's jr $ra instruction, which uses the value freshly popped off of the call stack into register $ra. frame: Now items within the frame can be accessed with offsets from the To illustrate how registers $s0 - $s7 are used, the previous example is rewritten to use them: The above code now utilizes registers $s0 - $s7 in order to have values effectively survive past the calls to subTwo. move $a1, $9 point of view: An important detail for 354 students writing MAL code and using storage of variables. When third returns, this is not a problem, but now second no longer has the appropriate address to return to, as the appropriate address was overwritten when second called third. The save

Consider the following abstract code choices. lw $a0, 24($sp) place current parameters into stack (space already allocated by Calling code then expects that $v0 will hold the returned value. The solution to the above problem, a solution implemented widely, is that of a stack in memory. described in the material on implementing functions. For correctness, it is important that all functions are implemented in the same way, as function calls require specific interactions between different pieces of code. sw $a2, 32($sp) For the purposes of this class, this restriction is ok, as we will never have a case of a function taking more than four arguments. current parameters are stored on the stack (by the parent) before as functions within the operating system.
save/restore it value for its parent (caller). procA: # receives 3 parameters in $a0, $a1, and $a2 change values in $a0 and $v0. sw $a1, 28($sp) While we can get around this problem in this case by being sure to map sub to a different register (e.g., $t2), this is another hacky workaround (which, incidentally, you should never do in your code, as it violates the MIPS calling convention). Relative to other calling conventions, the calling convention in this document is simplified. ���9����)o&�`�ͥ@S��j��J�f}dMe���J��~ɚ�'*k|���\W��ٺ�}w瞗���چ-L�?��X��Uk�t�ȡ�}��Y��D �T8N��ڐ&ں�����ذ�����}L�*O��#U����v�fk��'�]��O�{�"���݋����4[����� �ݞ. In a leaf procedure (which is a child, never a parent), use However, for the purposes of following the MIPS calling convention, for reasons we'll get into shortly, we are a bit restricted with what we can use. move $a1, $9 # overwrites procA's parameter in $a1 With this one instruction, the value on top of the call stack is placed into register $ra, resulting in a call stack that looks like the following: The value in register $ra now holds the address of the instruction that second should return to, specifically first's li $v0, 10 instruction (well, whatever instructions the psuedoinstruction li $v0, 10 translate to). Therefore, in general, you must assume that $a0-$a3 and $v0-$v1 Then, any and all procedures use those registers This section introduces registers $a0 - $a3. 0000007752 00000 n

We use optional third-party analytics cookies to understand how you use so we can build better products. Additionally, reasoning about which values are on the call stack at which times is not trivial. used for parameters, the values would be lost (just like the the simulator: The I/O instructions putc, puts, and getc are implemented 1816 0 obj <> endobj Again, it is generally better to map variables to registers in the order in which they appear in the original program. This means that if you call somebody else's function, say mine, you can gaurantee that the s registers will be the same in your function after my function edits. Pick one. 155 0 obj<> endobj This calling convention is optimized in the following ways: The rest of this document describes why we need a calling convention, and how the particular calling comvention used in this class works. We change the definition to the one below: While this definition does not actually do much of anything yet, it suffices as a minimal example to illustrate how a call is made. If a variable's value does need to live beyond a call, then generally it should be placed in one of the $s* registers. What $sp holds is a pointer to the top of the stack; $sp is, in fact, short for “stack pointer”. Specifically, this calling convention: In addition, relative to some of the calling conventions out there, this one is somewhat optimized, particularly when it comes to memory usage. Without further ado, the invariants you must preserve are listed below: Key Instructions and Transferring Control Flow, Functions that Call Functions Which Need Additional Registers. not move with respect to the current stack frame. 0000003817 00000 n For those variables that are not live, Once again, the call stack comes to the rescue here. To illustrate this idea, consider the code below, which shows changes from the previous code in bold. MIPS assembly has a calling convention which specifies that the t registers are callee saved, and the s registers are caller saved. This means that if you call somebody else's function, say mine, you can gaurantee that the s registers will be the same in your function after my function edits. Assumes that functions take no more than four arguments. Parameter Passing: The MIPS Way MIPS convention -- when passing parameters in registers, The aliases for $4-$7 are $a0-$a3. 0000001991 00000 n

As for why we decremented 4 as opposed to incrementing 4 is because on MIPS, the stack, by convention, grows from high addresses to low addresses. It is for this reason that it is so important that your code behaves according to the calling convention specified in this document.

The choice for using a $s or $t register may still not be obvious. The variable x is passed in register $a0, as it is the first argument. hޜUmOA�+�Qcp��Ӥ��$"�C�>��Z.^#���l)h ������>�r��ɠ%L���kh7LJ,���XA��x��8E&�� ��{�?�u~5K�_���n�����&��!�2�U�S������O���=f����G��, y �JC��/A�.� � ePQ���Y�����Q�~�f �c���ש��)�o?9�ZNN���Ք��u��q~�k�K��7�a5�1�E�sݦ��LX@���zu52���iO����h�v�ͺ��=+#٠{N�%YҺnn_�SS����EW7Ya]�"v�}?�|�f�7�%������`T��̼�h�Ŵ]5� ^�y��0�\����z3v=����xE�b��������[�튟������A���*�w-��P�����>҄�@��+��κ/m p� ��._�����I0�“,������L3�т�^��w[4@w8�P��̪��!0cQ��$E |q��0�V��ȷ��5��D6Č�Xh>�Nj�~ �4h�BCU��Z�C��.~��C��cd�������5���w1�{)�����5��O>(�$�z�P�p���9>��
The example re-written, to do things the MIPS way. sub $sp, $sp, 20 # allocate space for AR

Nearly all of the instructions in doSomething are devoted to manipulating the call stack, which is not ideal. puts, and getc. A parent (caller) presumes that no child (callee) will modify The aliases for $4-$7 are $a0-$a3. h�bbd``b`�N@�1H��lf@�9H05�dÀ�� � �l�L@:|���T�`m;@�@Bz��\����(R��H�!�3@� �� A endstream endobj startxref 0 %%EOF 428 0 obj <>stream For example, consider the following function: In order to call emptyFunction, this would be done like so: The above code snippet will jump to the code contained after the emptyFunction label (which we have yet to show), and put the address of the next instruction into register $ra. endstream endobj 1817 0 obj <>/Metadata 153 0 R/OCProperties<>/OCGs[1831 0 R]>>/Outlines 705 0 R/PageLayout/SinglePage/Pages 1809 0 R/StructTreeRoot 764 0 R/Type/Catalog>> endobj 1818 0 obj <>/ExtGState<>/Font<>/Properties<>/XObject<>>>/Rotate 0/StructParents 0/Tabs/S/Type/Page>> endobj 1819 0 obj <>stream second's first action is to push the value of $ra onto the stack, which dictates where second should return to. Parameters get passed to the operating system, and return values # set up procB's parameters When first calls second, the address of first's instruction after the call (specifically the li $v0, 10 instruction) is put into register $ra.

In general, you should remember the following: The above convention means that functions operate independently of each other when it comes to how registers are treated. the first 4 parameters are passed in registers $4-7. The Windows NT calling convention for the MIPS R4000 is similar to the other major MIPS calling conventions, but calling conventions for the MIPS are like snowflakes: Despite being made of the same underlying materials, no two is in it: What the mechanisms should look like from the compiler's register usage this Fall 2007 semester! -- The MIPS architecture does not really allocate a register for a 0 The call stack is a sort of data structure in memory, which stores the return addresses of the various functions which have been called in the past. move $a0, $24 # overwrites procA's parameter in $a0 The downside of registers $s0 - $s7 is that if you want to use one of them, it is up to you to save the register's current value and then later restore it. procedure is always passed in $a0. This is shown in the MIPS code below, which implements subTwo and doSomething legally according to the MIPS calling convention: The above code is valid, and it obeys the calling convention. The example above shows how to manipulate the call stack in order to have arbitrarily deep chains of function calls working properly. <]>> While there is no restriction on which registers you map to here, it is generally preferable to map variables to registers in the order that they appear in the program.

This section outlines a strategy for mapping variables to different registers.

You should never need more than four arguments in this class.