1 / 19

Defining and calling procedures (subroutines) in assembly

Defining and calling procedures (subroutines) in assembly. And using the Stack. Lecture Objectives. Define procedure (or subroutine) Explain the MIPS calling convention for procedure calls. Define the term program counter

liz
Download Presentation

Defining and calling procedures (subroutines) in assembly

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Defining and calling procedures (subroutines) in assembly And using the Stack CS-2710 Dr. Mark L. Hornick

  2. Lecture Objectives Define procedure (or subroutine) Explain the MIPS calling convention for procedure calls. Define the term program counter Explain the relationship between the caller and callee in a procedure call Explain the purpose for the stack when invoking procedures Explain the relationship between characters and strings. Explain the three main mechanisms for representing strings in memory. Explain the relationship between the 5 MIPS addressing modes.

  3. In Java, a method implements a procedure that can be called from other parts of a program public static void main(String[] args) { int x=1; doSomething(); int y=computeSomething(x); } private static void doSomething() { // no args or return… } private static intcomputeSomething( int x ){ … doSomething(); … return value; } CS-2710 Dr. Mark L. Hornick

  4. When a procedure is called, execution jumps to that procedure’s instructions and then returns to the statement following the call public static void main(String[] args) { int x=1; doSomething(); int y=computeSomething(x); } private static void doSomething() { // no args or return… } private static intcomputeSomething( int x ){ … doSomething(); … return value; } CS-2710 Dr. Mark L. Hornick

  5. Regardless of the location of the call, when the procedure ends, execution always resumes with the statement following the call public static void main(String[] args) { int x=1; doSomething(); int y=computeSomething(x); } private static void doSomething() { // no args or return… } private static intcomputeSomething( int x ){ … doSomething(); … return value; } CS-2710 Dr. Mark L. Hornick

  6. Assembly languages support procedures • Like methods in Java, procedures in assembly are used to implement instructions that you will call from other parts of a program • Like methods, procedures may (or may not) take arguments and may (or may not) return values • In assembly, the instructions for a procedure don’t look any different from the rest of the code – the difference is how you jump to that code: • jalproc_label # jal: Jump and Link • The jalinstruction “calls” the procedure beginning at the address represented by the label “proc_label” • In a jalcall, the address of the next instruction following the call (the jalinstruction) is automatically put into $ra– the Return Address register – to “link” it back to the call location.

  7. The return address register $rais used to “link”, or “remember” the next instruction to execute after returning from the procedure. 0x00400000 addi $t0, $t0, 1 # sample instruction 0x00400004 jal proc1 # call procedure at proc10x00400008addi $t0, $t1, $t2 # sample instruction … proc1: # label of procedure0x00600000 addi $t0, $t0, 1 # sample instruction 0x00600004 addi $t1, $t0, 2 # sample instruction 0x00600008 jr $ra # “return” When jalis called, the address 0x00400008 is stored in $ra Program execution jumps to the first instruction in proc1 When proc1 returns, program execution continues with instruction 0x00400008 CS-2710 Dr. Mark L. Hornick

  8. Only one instruction should ever be used for returning from a procedure: jr • jr $ra #jump to register • The return address (the address of the instruction that immediately followed the jalinstruction must be supplied as an operand to the jr instruction • jris the ONLY way to return from a procedure • NEVER use a plain jto return • Also, never use jto call a procedure CS-2710 Dr. Mark L. Hornick

  9. Now consider another call from within a called procedure: 0x00400000 addi $t0, $t0, 1 # sample instruction 0x00400004 jal proc1 # call procedure at proc10x00400008addi $t0, $t1, $t2 # sample instruction proc2: # label of procedure0x00500000 addi $t0, $t0, 1 # sample instruction 0x00500004 addi $t1, $t0, 2 # sample instruction 0x00500008 jr $ra # “return” proc1: # label of procedure0x00600000 addi $t0, $t0, 1 # sample instruction 0x00600004 jal proc2 #call procedure at proc20x00600008 jr $ra # “return” When jalis used to call proc1, the address 0x00400008 is stored in $ra. What happens to $ra when jal is used within proc1 to call proc2? CS-2710 Dr. Mark L. Hornick

  10. CS2852 Review: Stack A traditional CS data structure • Classical semantics (behavior) • Elements can only be inserted and removed from the front of the collection • This is known as Last-In, First-Out (LIFO) • Less commonly: First-Out, Last-In (FILO) • Random-access is not defined CS-2710 Dr. Mark L. Hornick

  11. JCF Stack – behavioral methods • The naming for the structure and the methods is an analogy for how the data elements within the structure are accessed • Principal methods that define behavior: • push() – place an element on (top of) the stack • pop() – return and remove an element from the (top of the) stack • peek() – return the top element of the stack • Without removing (popping) it CS-2710 Dr. Mark L. Hornick

  12. Most CPUs have a built-in implementation of Stack To start of memoryat 0x0 • The actual stack “data structure” is just an ordered collection of bytes in a section of memory known as the heap that lies between the .data and .kdata sections (in MIPS) • A special register ($sp, for Stack Pointer) is used to keep track of the start of the stack • Initially, the stack is empty • In the MARS default memory configuration, $sp is automatically initialized to 0x7FFFEFFC • By convention, the stack starts at (or very near) the end of data memory – more on memory layout later .data 0x10010000 - - - 0x1003FFFF 0x10040000 - - - 0x7FFFEFFA 0x7FFFEFFB 0x7FFFEFFC 0x7FFFEFFD 0x7FFFEFFE 0x7FFFEFFF - - - 0x80000000 0x80000001 .data .data $sp .data .ktext .ktext To end of memoryat 0xFFFFFFFF CS-2710 Dr. Mark L. Hornick

  13. The front of the stack grows “downward” towards lower memory as data is “pushed” onto the stack. To start of memoryat 0x0 Each successive “push” of data onto the stack effectively decrements the stack pointer $sp to a smaller address: addi $t0, $zero, 0x12345678 #load value into $t0 sw $t0, ($sp) #push $t0 onto stack addi $sp, $sp, -4 #decrement $sp .data 0x10010000 - - - 0x1003FFFF 0x10040000 - - - 0x7FFFEFFA 0x7FFFEFFB 0x7FFFEFFC 0x7FFFEFFD 0x7FFFEFFE 0x7FFFEFFF - - - 0x80000000 0x80000001 .data .data $sp after decrement $sp at start 0x12 0x34 0x56 0x78 .data .ktext .ktext CS-2710 Dr. Mark L. Hornick 13

  14. 0x00400000 addi $t0, $t0, 1 # sample instruction 0x00400004 jal proc1 # call proc10x00400008adi $t0, $t1, $t2 # sample instruction … proc1: # label of procedure0x00600000 sw $ra, 0($sp) # push $ra onto stack0x00600004 addi $sp, $sp, -4 # decrement $sp0x00600008 jal proc2 # call proc20x0060000c addi $sp, $sp, 4 # increment $sp 0x00600010 lw $ra, ($sp) # pop $ra from stack 0x00600014 jr $ra # “return” .data .data .data $spafter decrement At the beginning of every procedure: Push $ra onto stack, saving it Decrement $sp by 4 bytes At the end of every procedure: Increment $sp by 4 bytes Pop $ra from the stack Return to caller 0x00 0x40 0x00 $spat start 0x08 .data .ktext .ktext To end of memoryat 0xFFFFFFFF CS-280 Dr. Mark L. Hornick

  15. What happens if a nested procedure uses the same registers as the calling code? • Every procedure must • At the start of the procedure: • Push the $ra register onto the stack • Push the values of all $s registers onto the stack in order to restore them later before returning. • Decrement the stack pointer $sp appropriately • <do whatever the procedure does, including using $t registers at will> • At the end of the procedure, in reverse order: • Pop the $ra register from the stack • Pop the values of all $s registers from the stack in order to restore them later before returning. • That’s why $s registers are called “saved registers”! • Increment $sp appropriately • Return to the caller • Before calling a procedure, the calling code must: • Push any $t, $v, $a registers it is using onto the stack, since the called procedure may arbitrarily change any of those registers • After calling a procedure, the calling code must: • Pop any $t, $v, $a registers it was using from the stack, since the called procedure may have arbitrarily changed any of those registers

  16. What about procedure arguments and return values? By convention: • Registers $a0-$a3 are used for procedure arguments • The calling code must place values into the registers before calling the procedure! • The calling code must save the $a registers before the call, since the procedure is free to modify those registers! • If needed, the calling code must restore the $a registers after the call. • Registers $v0 and $v1 are used to represent a procedure’s return value. • $v0 is typically all that is needed • $v1 is only used if a 64-bit value needs to be returned • 64 bits are needed when the return value represents a long int or a double (more on that later in the course) • The calling code must save the $v registers before the call, since the procedure is free to modify those registers! • If needed, the calling code must restore the $v registers after the call.

  17. What if a procedure takes more than 4 arguments? By convention: • Registers $a0-$a4 are used for the first 4 arguments of any procedure. • If additional arguments are required, the calling code puts them on the Stack before calling the procedure. • Once the procedure is called, it gets the additional arguments from the Stack

  18. Example showing how the calling code would put a 5th argument on the stack, and how the procedure would retrieve it .data 0x003FFFEC addi $a0, $zero, 1 # arg1 in $a0 = 1 0x003FFFF0 addi $a1, $zero, 2 # arg2 in $a1 = 2 0x003FFFF4 addi $a2, $zero, 3 # arg3 in $a2 = 3 0x003FFFF8 addi $a3, $zero, 4 # arg4 in $a3 = 4 0x003FFFFC addi $t0, $zero, 5 # arg5 in $t0 = 5 0x00400000 sw $t0, ($sp) # push arg5 onto stack0x00400004 addi $sp, $sp, -4 # decrement $sp0x00400008 jal proc1 # call proc10x0040000caddi $sp, $sp, 4 # increment $sp … proc1: # label of procedure0x00600000 sw $ra, 0($sp) # push $ra onto stack0x00600004 addi $sp, $sp, -4 # decrement $sp 0x00600008 lw $t1, 8($sp) # load arg5 from stack …0x0060001c addi $sp, $sp, 4 # increment $sp 0x00600020 lw $ra, ($sp) # pop $ra from stack 0x00600024 jr $ra # “return” .data $sp after 2nd decrement 0x00 $sp after 1st decrement 0x40 0x00 0x0c $sp at start 0x00 0x00 0x00 0x05 .data .ktext .ktext To end of memoryat 0xFFFFFFFF CS-280 Dr. Mark L. Hornick

  19. Operating system services The MARS simulator provides a small set of “service routines” • Service routines are procedures provided by an operating system that are made available to a user-written program • Service routines in MIPS are not accessed via “jal” • Instead, a special instruction “syscall” is used. • An argument provided via $v0 (!) indicates which service routine to invoke • Arguments to the service routine are provided via $a0-$a4 Example: print an integer value to the console addi $a0, $zero, 5 #load value to be printed addi $v0, $zero, 1 #service routine 1 means “Print integer” syscall #invoke the service routine See the MARS online help for more information about all available service routines. CS-280 Dr. Mark L. Hornick

More Related