and we're going to look at lc3 and mips assembly uh and they're essentially very similar as you have seen so far with some idiosyncrasies in terms of the differences in instructions and these are the same readings that we discussed so basically we're going to look at some programming constructs talk about debugging a little bit more about principles than actually real detailed examples because detailed examples are actually quite too detailed to cover in uh even one lecture actually uh but you can study the examples on your own certainly we're going to talk about conditional statements and Loops that are important and then arrays and if you have time we're going to talk about function calls if not you can study them on your own but they're no different from function calls and any other isas if you will so remember we we're still talking about the one model Oney machine and instruction cycle these are things that you should keep in in the back of your mind we're going to build our first lc3 program by using conditional branches for looping essentially and this essentially we want to write a very simple program that has 12 integers and these integers are stored in addresses hex 3100 to hex 31 OB and usually the way you go about uh solving a problem in remember we're solving problems in computers and the first step is really translating the pro problem to an algorithm right and essentially to do that we actually create a flowchart of the algorithm in this case the flowchart or the algorithm is very low level as you can see because we're going to write programm in assembly later on so basically you can see that we even decided the register assignments so we're going to put the address of the first integer in 3100 over here we're going to put uh the counter in R3 and then we're going to put the number of integers in R2 over here uh so R1 is the initial address of integers as you can see R2 R3 will store the final result of the addition and R2 is the number of integers left to be added right at this point so that's this is the initialization part almost always algorithms have initialization part and that's what we're going to do over here and then the first step is to test whether R2 is equal to zero meaning whether we have any integers left to be added if it's not equal to zero then we do uh the addition if it is equal to zero which means that we reached the end of all the integers to process then we actually get out of the loop and do whatever else maybe output this to a screen for example right okay so basically uh are we done with all integers that's what this is checking if we're not done we load the first integer into a register uh remember that R1 specifies the address and that's doing the loading and then we essentially accumulate the value in R3 increment the count uh or increment the address and decrement the count of integer base and that's what it is and then you basically keep looping okay so hopefully this is very similar and simple and you've you've already written some programs in your life in dth for sure but if you're taking this course as the first course then this may be your first program to actually write uh but that's not true at eth U so B basically the next step is translating all of these to instructions in the ISA and that's what this does this directly goes into machine code of course and we use conditional branches to uh create a loop and these are the instructions as you can see so you can see that there's a load effective address that loads uh a value into 3100 and this is basically uh what we do in the instructions so this the load address as you can see over here here and then we reset the registers the top two things over here R3 and R2 and then we initialize the counter as you can see over here R2 and then we basically check the condition that's over here and then we jump out if the condition is true if not then basically we execute this block over here load the value in integers and then accumulate it and then increment the address you can see that different form of ads are you use add register and add immediate over here and then decrement the uh counter of integers uh increment the address we go to the next address in the next iteration and then unconditionally branch nzp is unconditional Branch unconditionally Branch back to loading the value right that's what we're doing over here uh or or checking the condition sorry not loading the value because we need to check the condition first because that's our Loop exit uh place so basically you need to get the branches right right that's the key point over here if you're doing assembly programming you should not Branch to here you should Branch to 304 over here okay so hopefully that's clear right and uh you know actually ex exactly how to execute all of these instructions in the lc3 data path uh that I shown you earlier I'm not going to go through this in detail again but everything that we have seen in the previous program you've already seen uh in the execution of the lc3 data path I see a hand raised is there a question uh I see a hand raised by Alexander okay maybe it was a mistake that's also fine uh if there's no question then I will move on okay uh okay so basically that was our first program and you know exactly how to execute every single instruction in that program now let's raise the abstraction level a little bit and talk about programming because based on everything we have seen right now now we know exactly how instructions execute we're going to show you more of that later next week uh now you know actually how to build programs that can execute on a real machine and you know how the real machine is built based on the combinational and logic structure so nothing is Magic at this point nothing really should be magic at this point in terms of how you can go from a transistor all the way to assembly programming and now we're going to close the gap uh for for assembly programming so we're going to talk about programming now uh from the high level so you have a task uh and programming requires dividing a task in other words a unit of work into smaller units of work so it's all of the programming is really divide and conquer in the end and the goal is to replace the units of work with programming constructs that represent presentent that part of the task that you're uh subtask let's say and there are three basic programming constructs uh sequential construct conditional construct and iterative construct and our um our instructions are actually enabling these constructs instructions in the ISA so sequential construct is kind of obvious you have it has to be decomposed and you can break it down into subtest one following the other so basically you break it out into two subtests so that you can think about the program uh in an easier way let's say or algorithm okay so hopefully that's obvious conditional construct is essentially uh enables you to do one of the subtasks but not both so it basically enables you to test a condition and based on the condition execute one task and if the condition is not true execute some other thing right and clearly this is an if and else contrast right either subtask maybe do nothing after the correct subtask is completed the program moves onward uh if you will so you can Implement IFL statements or switch case statements as we have seen earlier and ver log also implements these as you remember so iterative construct is used to if the task consists of doing a subtask a number of times but only as long as some condition is true so this is used to implement Loops as you can imagine first you basically test a condition if it's false you don't do it if it's if the condition is true then you do the top desk it could be the other way around also you could you could actually test the exit condition also and if the condition is true you could exit the loop as well right so basically it's a looping construct let's say and if the condition is still true you keep doing the subtask for Loop while loop do while loop are examples of Loops so let's take a look at these constructs in an example program I'm not going to go through this program in detail actually uh because we don't have time and it's I think trivial to go through it if you will uh so the example program is going to count the number of occurrences in a character in a text file it's going to use all of the construct sequential conditional and iterative and we will see how to write condition and iterative con structs using conditional branches so counting occurrence of a character basically we want to write a program that counts the occurrence of a character in a file so we're going to get the character to search from the keyboard using a trap instruction that's going to be the novelty we will learn at the end of this but we're not going to go into how it's implemented and the detail of it so we're going to interact with the uh keyboard over here and the file will finish with the character end of text eot this a special character called a sentinel character if you didn't know about the word Sentinel it designates the end of something essentially in this example eot is set to four for example it could be something else output will be output result will be placed onto the monitor using another trap instruction essentially again you will see that soon but this is how I break my program into the constructs sequential uh conditional and iterative again I'm not going to go through this in detail but you need to initialize the count uh and you remember the constract pictures over here you need to initialize the count initialize a pointer uh get the input character from keyboard get the get the character from file that we're going to compare to the input character and then uh if the character get that we got from the file is not end of text then we keep looping what do we do if we Loop uh we check if the end of file if it's not the end of the file we check if there's a match if there's a match we increment the counter of the characters that match the input character if there is not a match we don't increment and then we get another character from the file and then increment the pointers and the initial address as you can see over here and then we keep doing the same thing until the character we read from the file is end of text right so that's the iterative construct and I've already described all of these actually uh and then if at the end we prepare the output we exited the loop we're done with the file and we prepare the output to WR don't worry about exactly what this means this basically converts the output to an S key character that can be displayed by the Monitor and then we output to the Monitor and the monitor displays the character in its own format okay and then we halt the program using another trap instruction to stop the program because we're done essentially so this is a full program and you can read again the hair the pad and Patel chapter that houses this program uh so trap instruction basically let's talk about trap instruction because it's important this is the operating system hard face essentially in lc3 m has its own instructions it invokes a service call essentially operating system service call in assembly it looks like this a machine code it looks like this is very simple basically and you have a trap Vector basically the up code is 1111 and trap Vector specifies what you what you ask the operating system to do so for example if you say trap Vector 23 you basically ask the operating system to get a character from the keyboard right or if you use trap 21 you ask the operating system to Output a character to the monitor if you use trap 25 you ask the operating system I'm done with the program halt the program finish the program basically so we're not going to go into how this is implemented if you're really interested you should really read the appropriate chapter uh input output for example uh from Pat and Patel but we don't have time in this semester to really go into it in systems programming you will go into it more but uh uh maybe in another version of this course we can go into it but not just not this version so this is the program that I that we wrote and this also in in your Pat and Patel book that basically implements uh the constructs that we showed you earlier that basically implements this flowchart and again I'm not going to go through this in detail you can convince yourself that the program does what it does uh but again uh we don't have time to go through the detail you can see that we use conditional Branch instructions to create loops and if statements uh and you can do reverse engineering to identify conditional constructs and iterative constructs like what I show you over here uh but again uh we don't have time to go through this in detail again again nothing is hard over here it's just translating the program into Assembly Language and then the machine code later on you can also start from the machine code and reverse engineer the program as well right and you can see that there's a starting address of the file over here so file actually is stored in memory in this case it's a memory mapped file but again we're not going to go into that uh in this course so let's talk about debugging because it's going to be something important that you do in all your programming including your very log programming and this is the process of removing erors and programs uh it consists of tracing the program keeping track of the sequence of instructions that have been executed and the results produced by each instruction it's clearly a useful technique right and one way of making it even more usefulness to partition the program into Parts like modules and examine the results computed each module separately so high level language debuggers can help you clearly there are many many examples of this that I'm not going to go into machine code debugging provides you Elementary interactive debugging operations so let's take a look at interactive debugging operations when debugging interactively it's really important for you to be able to put some values into to memory and registers you're at a very low level as an assembly programmer right you need to be able to test the execution of a part of a program in isolation maybe one instruction right execute instruction sequence in a program by using the Run command so if you have a debugger that supports this you can run instruction by instruction right and run command executes until Hal instruction or until a breakpoint so you can uh step and command basically you can execute a fixed number of instructions you could step one for example you could make execute every instruction one by one examine the the results and see what you expect uh if what you expect is in the registers and memory and you can stop the execution when desired in debugging clearly right you can do that by setting a breakpoint command uh by stopping execution at a specific instruction you set a breakpoint in a particular point where you want to examine the memory and register values and when the after this you can examine what's in memory and registers at any point in the program if you have this infrastructure that way you can step through the program so this is very useful clearly and doing this in very log is is also very useful except very log is very inherently parallel right assembly because of the Oney model we execute one instruction at a time right so you can actually say I'm going to in execute one instruction at a time and then you can see what the result of that instruction is and if what you expect at the high level as a programmer is satisfied right so for example we have a multiply uh operation in lt3 a program is necessary to multiply since lt3 does not have a multiply instruction and the following program multiply values R5 R4 and R5 basically and again initially R4 is 10 R5 is three I'm not going to go through it in detail but the program produces 40 the question is what went wrong and you can examine it by yourself and do to do so it's useful to annotate each instruction so again you have if you're given the machine code you can easily annotate these instructions and say these are the instructions that I have and if you examine the instruction and the contents of the registers after the execution of each instruction you may find out that the the correct result is here after uh three iterations but after some point branch is taken and the branch should not be taken if R5 is equal to zero because then you would be multiplying things by more than once so if you go over here R4 is 10 R5 is three and the program produces 40 clearly program should produce 30 the program iterated once more in the loop basically one too many times because the branch condition codes were set wrong the conditional Branch should only be taken if R5 is positive so basically we did a mistake over here in the program we set the zbit whereas we shouldn't be setting the zbit we should not be checking the zero condition over here because that uh is a boundary condition in which the program leads to one more iteration which should it should not uh execute right so the correct instruction should have been BRP uh as opposed to brzp right so we can actually find the uh Pro Problems by executing the uh uh debugging the program by executing instruction by instruction clearly or by setting break points I'm not going to go into the details clearly so you can do easier debugging with break points as we said previously we examine the instruction instruction by instruction but you can actually set a breakpoint at the branch and see where the Branch goes and you can examine the results of each duration of the loop as opposed to examin the results of every single instruction in the loop and this way you can actually look at interesting things that you care about and you can still find the problem basically okay so does this program work if the initial value of R5 is zero is another question and I'll let you answer that basically that's another Corner case basically if R5 starts with zero does this program still work and the answer is no this program doesn't work basically that's a problem uh so basically you should test the condition you should test whether R5 is zero first uh to to really understand uh whether this program to truly make this program work so there are multiple boundary conditions that this programmer was not careful in dealing with one boundary condition was uh What uh the result uh uh should have been uh and uh what the result so I think I see a question why doesn't it work if R5 is equal to zero because you can see that uh you basically do the addition first right you add R2 to R4 and then you uh R5 becomes minus one over here so remember the value of R5 uh is uh yeah basically you you add R4 to itself basically you get the result 10 if R5 is zero which you you should not get you should really get zero because you didn't check the boundary condition at the beginning okay uh okay so we discussed the break point so I went to uh forward okay so basically a good test should consider the corner cases meaning unusual values that the programmer might fail to consider and again this is not a well written program because it didn't consider many Corner cases including whether r five was zero and whe whether uh when when you should really Branch over here okay so very quickly let's talk about conditional St statements and loops and mips assembly because it's going to be useful in your Labs again if you have to go somewhere feel free to drop off you can watch this later or you will learn this anyway in your Labs uh by yourself but I'm going to cover it relatively quickly so that you have at least if you want to watch it you can actually watch it uh if you if you cannot attend it right now uh but again you're going to do this in your Labs as I said so you're going to learn it by hand anyway and the best way of learning is really by hand on learning so in in myips we can create conditional constructs with conditional branches as we discussed you can do Branch if equal as we discussed and we're going to see an example of Branch if equal so high level code looks like this if I is equal to J F becomes G plus h and then independently of that we subtract I from F this is what the program looks like you could call the silly function again right and myip assembly looks like this basically one way of use doing this uh encoding this in myses or programming this in myses basically we Branch not equal uh if S4 uh S4 and S3 basically we check if S3 and S4 are not equal and assume that S3 and S4 contain I and J and if they're not equal we skip the ad that's what this uh instruction says right we go to L1 which is the label of the next instruction so if S3 and S3 S4 are not equal Ranch not equal then then go to L1 if they're equal that means that we're going to do the ad so this what it is basically it's very simple you compare to two values and uh you Branch if the two values are different okay so if if the statement was a little bit different you had an if and else statement now you need to do something a little bit more right basically we use an unconditional Branch to skip the else subtask if the if subtask is the correct one so what does this mean basically it means this we write the code like this this is the correct Corr responding M assembly code to the high level code we again have the branch not equal if S3 is not equal to S4 meaning I is not equal to J we skip the ADD and we go to uh uh done essentially sorry we in this case we we do the else right yeah this a different code so we basically need to do the else which is the L1 over here because if I is not equal to J we do f equals F minus I which is implemented by the subtract instruction but if the BR if this Branch condition is not true we do the ad but we should not do the else to be able to to enable that we have an unconditional jump basically if we do the ad we should really jump to done and skip the subtract so hopefully that's clear to be able to implement if and else statement you need two branches one is a conditional branch and the other is an unconditional jump that skips the else part right conditional Branch skips the uh the uh essentially the target uh that that is supposed to be executed if the condition is true and unconditional jump skips the the part that is executed the sub subt that is supposed to be executed if the condition is false there's a question can you jump back in the code absolutely you can jump anywhere basically as you can have a label over here saying for example at the beginning of an earlier Loop you can you can have a label at the top for example and you jump to that uh so you can jump anywhere as long as your offsets are fine BAS Bally as long as you don't violate the offsets but even then you need to use a different addressing mode if you want to jump to anywhere in the code right okay so basically I already said this you compare the two values and if they're different jump to L1 uh uh otherwi to execute the L sub task over here right and uh this unconditional jump jumps to done after executing the if subtask okay while loop is a little bit more complicated as in lc3 the conditional branch checks the condition and the uncondition BR jumps to the beginning of the loop over here we've seen it in lc3 now we're going to see it in myips it's going to be very similar basically you initialize the p uh Power and x value so here this Loop determines the power of two equal to uh 128 uh which is a very simple calculation as you can see and initially power is set to One X is set to zero so you need to set those values plus the 128 to compare to and while loop basically does a branch equal over here it has a conditional Branch to check if the condition is still hold so you need to check the condition first before entering the loop otherwise you may execute the loop once too one too many times right as we saw earlier in the buggy multiplication example right here it's not multiplication but it's really figuring out the power uh raised to the two power of two right okay so basically that's what this Branch equal does and then there's conditional Branch to the beginning of the loop so we execute the loop once and then unconditional branch and then we check the loop exit condition again well whether the power is not equal to 128 so if the power is equal to 128 then we're done if the power is not equal to 128 we execute the ration of the loop multiply Power by two increment X by one and then go to the beginning of the loop and then check if power is equal to 128 again and you keep doing this until power is equal to 128 okay the implementation of the for Loop is very similar to The V Loop essentially this is another loop that looks that is different it's a for Loop you can see that you're adding integers from zero to 10 10 is not included over here and essentially it looks very similar right basically you set set the variable sum I and also you set something to 10 so that you can compare I to 10 at the beginning if I is is equal to 10 you jump out of the loop if I is not equal to 10 you execute the loop iteration and then you have an unconditional jump back to the branch equal right essentially the same thing basically very similar to the Y Loop that we saw earlier okay so you could have use a for Loop by using the set less than which is a way of setting the registers this is like condition codes in a little bit but you set a general purpose register not a condition code so we use the set less than for the less than comparison so let's take a look at this this is another trick you can use for example so basically you again add the powers of two from one to 100 that's another uh loop that does that particular task and to be able to do that you initialize sum an i and then until I is less than 101 you basically find the powers of two and like this and then add it to the sum right and to be able to do that you have some initialization and then you do the set less than basically this what this set less than does is okay I already said this set less than is essentially the statement if the value in register z s z is less than the value in register t0 the destination register gets one otherwise it gets zero okay so it's basically this statement implemented with one instruction right it's it looks nice basically it's a very high Lev statement if you will you can directly Implement a highle language statement that looks like this and then uh basically it basically tests the condition and sets it less than and then you check whether T1 is equal to zero if T1 is equal to zero then basically that means that you need to exit the loop right if not equal to zero then you can you should stay in the loop and do the loop iteration and then basically do check the condition again and again but you should also execute the set less than BQ in this case you set you set less than a register and then check whether that register is equal to zero or one to implement the looping mechanism right another way of implementing you could do it you could have done it in some other way also clearly so here we have shift that logical this is essentially multiplication by two right multiplying by two is the same as shifting left logical in binary uh by one uh and we don't use a multiply over here because Shi logical is much simpler and faster in Hardware okay let's go into a little bit more into mips uh again this is going to be very uh simple to many people who know programming so you don't really need to uh study this if you will but it's instructive I think to look at how the arrays are implemented in myips uh accessing an array requires loading the Base address into a register as we have seen earlier so in memory the array looks like this basically you have a base register that is that points to the beginning of the array and then uh each array element is a word in this particular case and then basically each word is in the next word location which is which has this spite address as you can see over here on the left so in mips uh this is something we cannot do with a single immediate operation loading the base register so what do we do we use what we learned earlier load upper immediate Plus or immediate right Lui and or I we've seen this before if you want to load this address that we know into a register let's say S zero we first load the upper immediate 1 2 3 4 to the top 16 bits of the s z register and then or uh the register with the 16 bits coming from this immediate value 8,000 over here and then you now you have this address this Base address of array uh in s z so now you can see how we can construct an address this is very similar to Lea load effective address in lc3 except it's more powerful because now you can uh load a a 32-bit value over here so let's take a look at how we manipulate arrays basically if you want to manipulate an array we first load the Base address of the array into a register using Lui and Ori as you can see over here we're going to assume that that's the Base address of the array now the Base address of the array is in sdo and we're going to use things that we have seen earlier basically uh so if you want to get the element zero we calculate the address as Base address plus offset zero if you want to load element one we calculate the address as Base address plus 1 times four bytes per vert that's why this offset is four and then you can actually do the multiplication do the store and then do the multiplication and the store multiplication again is shift left logical because that's simpler to do than just a multiply operation now let's talk about function calls and this is the last thing that I'm going to talk about and conventions it's going to be interesting because uh assembly is interesting I think here but clearly we want functions or procedures or modules in a programming Lang uh programming language because this enables us to reuse code and we have frequently accessed code it makes a program more modular and readable and functions have arguments and return value or values so this is one example right you have a main function over here that gets executed and then you have a su function that gets called that essentially Returns the sum of the two parameters two arguments that it's given so let's define something so calling function is called the caller so the main function is the caller over here and the called function in this so as I said call called function is called the call so some function is the call over here okay so there are a bunch of conventions that people provide when you do assembly programming so that you don't destroy registers unnecessarily and so that you can actually have much more modular code if you obey these conventions this is also called the programming interface or yeah essentially programming interface to the assembly language for a given architecture if you follow these conventions and if everybody follows these conventions you don't need to save or restore some registers as we will see so basically caller passes arguments jumps to call E call E performs the procedure and Returns the result to call so that's the and then returns to the point of the call basically let's take a look at this but call must not overwrite registers or memory needed by the caller and this is really important if the call overwrites some registers or memory needed by the caller when you return back to the caller too bad you don't have the registers you need you don't have the memory you need so that's why we need conventions basically so there are some conventions mips and lc3 and again these are conventions that you should obey if you want to actually be compatible with the rest of the world so in myips you you can call a function or call a procedure using the jump and Link instruction in lc3 you can use a jump to sub routine jsr and jsr these are different ways of calculating the sub routine address basically or you can return and you can return from procedure in myips using the jump register instruction in lc3 can return from sub routine r instruction over here and the argument values are supposed to be stored in myips in registers a0 through A3 and the return value in myips is supposed to be stored in v0 okay so that's expectation and v0 is mapped to some register as we have seen earlier that I don't have over here again so basically let's take a look at a simple example this is our highle code the main function called a simple function that just returns and you have uh this in main function so the mips assembly looks like this so what this does is basically you have a jump and Link uh to simple and then you have the ad in the next instruction so simple in this case doesn't contain anything doesn't do anything except it returns back right to return back you just use the jump register register a so why register a because jump and Link was a special instruction jump and Link jumps to simple and saves PC plus4 in the return address register which is a special register in the general purpose register file R in assembly you can assume that after you do a jumpan link the return address meaning the instruction after jump and Link will be stored in RA in the call E okay so basically that's why you can do jump register ra and then go back to this add instruction that comes right after jump and Link hopefully that makes sense right this makes life easier in programming basically now you have programming support the hardware support or Hardware software interface support for uh function calls in the instructions set architecture right in lc3 you have a similar thing basically you have jsr or jsr that puts the return address in R7 so there's a specific register ra also has a number actually but basically R7 uh is the RA in lc3 but it's essentially the same thing uh okay so there's a very good question what happens if we call a function from within a function don't we overwrite ra then absolutely and then the if you do that the task of the simple function over here if it calls another function it has to save ra at that point basically and that's why we're going to introduce the concept of stack for example in a little bit so that's a very good question basic because somebody needs to say if you're going to overwrite a register that you're going to need later or somebody's going to need later you have to save it in memory and then reload it before it needs to be used okay basically as I said jump register ra jumps to address in ra lc3 simply uses the r instruction which is essentially a jump register uh but it's a specialized jump register which basically sets the PC to ra essentially okay so let's take a look at the high level code over here let's look at a little bit more complicated example so here uh we're uh we're looking at um a main that's called diff of sums it does something don't worry about it but you can you can see what it does basically it add f plus G and subtracts it from 8 plus I and then it basically Returns the result right so so now this is a little bit more sophisticated function so what does the main do basically main sets up the arguments so remember this is the convention a z A1 A2 A3 basically it's it can pass four arguments to the function and then it sets two three four five those arguments to and then it does jump and link to diff of sums and then diff of sums the arguments assumes that the arguments are in a0 A1 A2 A3 so there's some convention for sure that you need to obey to make this work uh and then uh it subtracts add add subtract and then puts the result into v0 and jump register array which goes back over here and then main takes the result and v z does whatever it needs to do with it basically too okay so basically we use the convention arguments are stored in a0 through A3 and the return value is stored in v0 okay I already said this basically and the return address is stored in ra again okay so there is a need for a stack for function calls for the reason that we just discussed actually based on the question that I received so if you look over here the diff of sums looks like this right t0 T1 s0 uh what if the main function was using some of those registers that was used by the diff of sums right t0 T1 s0 well too bad you're overwriting them right so if you remember over here we're using t0 T1 s z and we didn't think about this right if the main function was using t0 T1 and s0 the of sums is overwriting them uh and but we can fix this problem by using a stack to temporarily store the registers that we're overwriting and then restore them back after we're done with the function so the concept of a stack is basically it's a Memory area that's used to save local variables that we operate on temporarily it's a last in first out Q you may have seen this in other programming language courses the stack pointer is a special register actually points to the top of the stack it goes down in myips it's a convention again all of these things are conventions even the naming is convention right so it looks like this basically so you can push values on the stack and you can pop values out of Stack so look over here if you look over here the stack pointer points to this location this address it has this value maybe you can push two registers on the stack here that have two values a a b b c c DD and 1 one 2 2 3 3 4 4 now you added or pushed two values onto the stack and when you actually start before you start the function call you actually say oh okay I'm going to save the temporary registers that I'm going to work on just to make sure that no one is going to uh I don't uh I don't uh actually uh over write uh the calling functions registers right and you can push them on the stack and at the end of your function you can put pop them from the stack and put them back into the registers uh that uh where they were supposed to be so here two words are pushed on the stack let's take a look at this example so we we have the same function uh that we saw earlier it's it's writing t0 T1 s0 but we don't know if the calling function uses them so what we do is basically we allocate space on the stack to store three registers basically we do this to the stack pointer and then we basically store s t Z and T1 to memory locations on the stack and now we can overwrite because we store the old values of s0 t0 and T1 now we can comfortably overwrite t0 T1 s0 and then compute values based on that based on whatever we want to do and at the end before we do the jump register register a we load back the values that we pushed on the stack uh into T1 t0 and s0 to the corresponding register so this is called uh spilling values on the stack uh and filling values back from the stack we're spilling values on the stack because we're using some registers that we don't know if somebody else used that called us and then before the function returns we're going to fill the values back into the register so that the calling function sees the registers as they sent uh the register file to us okay that's the idea over here and then we deallocate the stack space because the stack pointer can also be used by the calling function basically right so stack pointer is a stack is a common memory area that's used by all functions and this is a very general way of saving and restoring registers as you can see so the question that was asked earlier uh ra right uh register a if you're going to overwrite if you're going to call another function inside diff of sum so if you're going to call for example another function you'd better save ra on the stack and uh get back ra uh uh after that from the stack uh uh when you do that again saving and restoring all registers requires a lot of effort in mips there's a convention about temporary registers so actually we did not need to save temporary registers assuming everybody obey convention again there is no need to save the temporary registers because the convention says temporary registers the calling function should not expect the values and temporary registers to remain the same after it calls a function okay that's a convention again these are programming conventions okay so there's a register saving convention that enables us to use temporary registers without worrying about the calling function but if we're using S zero we'd better save it because s doesn't isn't that part that's not part of that convention basically temporary registers are called nonpreserved registers they are not saved thus they can be overwritten by the function the function it's not the function's responsibility to save them essentially and but registers S zero and s s are preserved it's the or they are called Call Save which means that it's the functions responsibility to save going to overwrite them that's true for ra as well by the way okay okay so now we're done actually we covered a lot of interesting Concepts uh again you're going to learn this anyway at some point but hopefully it's interesting if you stay if you didn't stay that's fine uh you can watch it or uh if you really need it you can actually refer to the lectures uh when you need it from the labs uh but essentially we've covered all these Concepts relatively quickly