5.137 · exercise

Draw the frame: a struct on the stack

The program is paused inside scaled_rect, which keeps an int and a rect record in its frame. Fill in where each field sits.

The record's fields are equates counted from the start of the record (rect_width, rect_height, rect_area), and rect_s is where the record starts in the frame, so a field's offset from fp is rect_s plus the field's own offset. The frames view names each field after the record: rect_s.rect_width is the width field.

What is checked

  • the frame's size in bytes
  • the offsets from fp of scale_s, rect_s.rect_width, rect_s.rect_height and rect_s.rect_area
  • the offsets from fp of the saved fp and the saved lr

Check runs the program to the pause and compares each number with the frame the emulator draws there. A wrong number shows a hint, never the answer.

the program

// Build a rectangle record on the stack, scaled up, and print it.define(fp, x29)define(lr, x30)// struct rect { int width; int height; long area; }rect_width = 0                                  // 4 bytesrect_height = 4                                 // 4 bytesrect_area = 8                                   // a long starts on a multiple of 8rect_size = 16scale_size = 4                                  // intscale_s = 16rect_s = (scale_s + scale_size + 7) & -8        // the record holds a long, so it starts on a multiple of 8alloc = -(rect_s + rect_size) & -16dealloc = -alloc.datafmt_out:    .string "%d by %d, area %ld\n".text// scaled_rect(w0 = width, w1 = height, w2 = scale): prints the rectangle scaled up        .balign 4        .global scaled_rectscaled_rect:        stp     fp, lr, [sp, alloc]!        mov     fp, sp        str     w2, [fp, scale_s]               // keep the scale        add     x9, fp, rect_s                  // x9 = &rect        mul     w10, w0, w2        str     w10, [x9, rect_width]           // rect.width = width * scale        mul     w11, w1, w2        str     w11, [x9, rect_height]          // rect.height = height * scale        sxtw    x12, w10                        // widen before the multiply        sxtw    x13, w11        mul     x12, x12, x13        str     x12, [x9, rect_area]            // rect.area = rect.width * rect.height        ldr     x0, =fmt_out (paused before this line)        ldr     w1, [x9, rect_width]        ldr     w2, [x9, rect_height]        ldr     x3, [x9, rect_area]        bl      printf        ldp     fp, lr, [sp], dealloc        ret        .balign 4        .global mainmain:        stp     fp, lr, [sp, -16]!        mov     fp, sp        mov     w0, 3                           // a 3 by 4 rectangle        mov     w1, 4        mov     w2, 5                           // scaled up 5 times        bl      scaled_rect        mov     w0, 0        ldp     fp, lr, [sp], 16        ret

Paused before line 42 runs.

the frame at the pause

  • rect_s.rect_area
  • rect_s.rect_height
  • rect_s.rect_width
  • scale_s
  • saved lr (x30)
  • saved fp (x29)