1 / 10

Looping through an array of bytes

This article provides examples of looping through arrays, manipulating array elements, making function calls, and performing stack operations in MIPS assembly language.

Download Presentation

Looping through an array of bytes

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. Looping through an array of bytes • Example 1: /* a = array of char */ for(i = 0; i < 10; i++) a[i] = 0; • What’s going on here? Answer: Pointer arithmetic! for(char *p = &a[0]; p < (a + 10); p++) *p = 0; li $t0, 0 # t0 = i la $a0, a # a0 = &a[i] loop: bge $t0, 10, done sb $0, 0($a0) # a[i] = 0 addi $t0, $t0, 1 addi $a0, $a0, 1 j loop done: la $a0, a # a0 = &a[i] addi $t0, $a0, 10 loop: beq $a0, $t0, done sb $0, 0($a0) # a[i] = 0 addi $a0, $a0, 1 j loop done:

  2. Looping through an array of 32-bit ints • In this case, &a[i] is actually &a[0] + 4*i • add 4 to pointer inside loop • use lw/sw instead of lb/sb • Example 2: /* a = array of int */ for(i = 0; i < 10; i++) a[i] = 0; la $a0, a # a0 = &a[i] addi $t0, $a0, 40 loop: beq $a0, $t0, done sw $0, 0($a0) # a[i] = 0 addi $a0, $a0, 4 j loop done:

  3. Translate into MIPS • Example 3: /* a = array of int */ for(i = 0; i < 4; i++) { if(a[i]==a[i+1]) break; } • Example 4: /* a = array of int */ for(i = 8; i >= 0; i--) { a[i+1] = a[i]; } a[0] = 0; la $a0, a addi $t0, $a0, 16 loop: beq $a0, $t0, done lw $t1, 0($a0) lw $t2, 4($a0) beq $t1, $t2, done addi $a0, $a0, 4 j loop done: la $t0, a addi $a0, $t0, 36 loop: beq $a0, $t0, done lw $t1, -4($a0) sw $t1, 0($a0) addi $a0, $a0, -4 j loop done: sw $0, 0($a0)

  4. Function calls in MIPS • MIPS uses the jump-and-link instruction jal to call functions • jal saves the return address (the address of the next instruction) in the dedicated register $ra, before jumping to the function • jal is the only MIPS instruction that can access the value of the program counter, so it can store the return address PC+4 in $ra • To transfer control back to the caller, the function uses a jump-register instruction to the address that was stored in $ra: jr $ra • Arguments to functions can be “passed” by placing them, by convention, in registers $a0 to $a3 • Values are returned, by convention, in registers $v0 and $v1

  5. Warnings and Problems • Assembly language is untyped — there is no distinction between integers, characters, pointers or other kinds of values • You must “type check” your programs • Make sure your function arguments/return values are consistent • No warning if you pass an address of an integer (instead of the integer itself) to a function • A problem: What if a function uses a register that the main program needs after the function call? • Things get really nasty with nested/recursive functions • Solution: spill registers to memory (stack) • save “important” registers to memory before function call • restore these registers after the function call • Who spills? Caller or callee?

  6. Who saves the registers? • Argument 1: The caller knows which registers are important to it and should be saved. So caller should save. • Argument 2: The callee knows exactly which registers it will use and potentially overwrite. So callee should save. • Both approaches may wastefully save registers they don’t really need to. • But the caller and callee must not assume anything about each other • may be written by different people or companies • should be able to interface with any caller/callee • Solution: Caller assumes callee will destroy: $t0-$t9 $a0-$a3 $v0-$v1 Callee assumes caller will need: $s0-$s7 $ra

  7. NO!! $a0 may contain garbage at this point $sp 0x7FFFFFFF 0x00000000 stack Example • C++ code fragment: if(func(7) == 7) func: # free to modify $a, $t and $v registers jr $ra main: li $a0, 7 # set argument for call to func jal func # call func(7) bne $a0, $v0, else # test if func(7) == 7 • Since we want to preserve $a0 across the function call, we must save it before the call, and then restore it after the call. • MIPS stack grows LEFT, $sp points to “last used slot”

  8. $sp $sp Before Pushing elements • To push elements onto the stack: • “Grow stack” by subtracting from $sp • Store the elements into the stack (array) • Example: Push $t1 and $t2 onto stack addi $sp, $sp, -8 sw $t1, 0($sp) sw $t2, 4($sp) • Returning to our previous example: li $a0, 7 addi $sp, $sp, -4 sw $a0, 0($sp) jal func # restore $a0 bne $a0, $v0, else $t2 $t1 After

  9. $sp $t2 $t1 $sp $t2 $t1 Accessing and popping elements • You can access any element in the stack (not just the top one) if you know where it is relative to $sp • For example, to retrieve the value of $t2: lw $t2, 4($sp) • You can pop, or “erase,” elements simply by adjusting the stack pointer upwards • Example: addi $sp, $sp, 4 • Note: The “popped” data is still present in memory, but data left of the stack pointer is considered invalid

  10. Finishing the main example func: # free to modify $a, $t and $v registers jr $ra main: li $a0, 7 # set argument for call to func addi $sp, $sp, -4 # grow stack sw $a0, 0($sp) # save $a0 on stack jal func # call func(7) lw $a0, 0($sp) # restore $a0 from stack addi $sp, $sp, 4 # shrink stack bne $a0, $v0, else ... jr $ra • Unfortunately, main won’t return correctly! • Any time you do a jal, you must save and restore $ra

More Related