-2

Question

The program is supposed to do the following:

  1. Add up the first 6 data items ($1 to $6) stored at address label DATA.
  2. Store the sum of the first 6 data items to address label SUM1.
  3. Multiply the sum stored at address label SUM1 by 8, and store the result at address label MUL8. (loop then add)
  4. Add up the last 6 data items ($7 to $C) stored at address label DATA.
  5. Store the sum of the last 6 data items to address label SUM2.
  6. Divide the sum stored at address label SUM2 by 4, and store the result at address label DIV4.
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
thxr
  • 1
  • 1

2 Answers2

1

How do I do the BSR SUBR, and define the SUBR part of the code?

You can't solve this task without consulting the Programmer's Reference Manual
There's really nothing more to do for the BSR SUBR instruction that already does a 'Branch to Subroutine' (BSR). Defining the SUBR part is just a matter of writing down the instructions that will perform the six steps that were outlined in your task description and then execute a 'Return from Subroutine' (RTS).

To get you on your way, here's a detailed explanation for step 1

  1. Add up the first 6 data items ($1 to $6) stored at address label DATA.

In order to sum up 6 bytes from the array, we can load the first byte in a data register and then add the next 5 bytes from a loop.

Before the loop we:

  • load an address register like A1 with the address of the DATA label. The movea.l #DATA, a1 instruction does that.
  • load a data register like D1 with the loop count which is 5. The moveq.l #5, d1 instruction does that. To load small numbers in the range [-128,+127] always prefer moveq over move because it is both faster and has a smaller encoding .
  • load another data register like D0 with the first byte from the array. The move.b (a1)+, d0 instruction does that. Because this instruction uses the post-increment addressing mode and because the size attribute is byte, the address held in the A1 address register will automatically increment by 1. This way we can step through the array.

In the loop we:

  • add the next byte to the chosen D0 data register. The add.b (a1)+, d0 instruction does that.
  • decrement the loop count we have in the D1 data register. The subq.l #1, d1 instruction does that. To subtract small numbers in the range [1,8] always prefer subq over sub/subi because it has a smaller encoding and is much faster then subi.
  • branch back to the top of the loop only if the decrement on the loop counter did not produce 0. The bne.s loop1 instruction does that.
    movea.l #DATA, a1
    moveq.l #5, d1
    move.b  (a1)+, d0
loop1:
    add.b   (a1)+, d0
    subq.l  #1, d1
    bne.s   loop1

I'll throw in the next step since it is rather trivial

  1. Store the sum of the first 6 data items to address label SUM1.

Step 1 left the sum in the D0 data register. Just move it to the SUM1 variable but be sure to use the correct size tag which is .b in accordance with how the SUM1 variable was defined:

move.b   d0, SUM1

Good luck with steps 3 to 6...

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • N.B.: Instead of `subq.l #1,d1; bne.s loop1`, one can use `dbf d1,loop1` (this just uses the lower word of `d1` as a counter, but works in this case as well). – chtz Sep 06 '22 at 07:22
  • @chtz This creates an off-by-one. `subq.l #1,d1; bmi.s loop1`, could be directly replaced by `dbra` (dbra branches until -1 in the count register) – tofro Sep 06 '22 at 08:09
  • @tofro You are right. This would also require to reduce the original count in `d1`. `dbf/dbra d1,label` is actually equivalent to `subq.w #1,d1; bcc label` (except for not altering the flags) – chtz Sep 06 '22 at 09:12
0

SUBR isn't an instruction, it's just a placeholder for a label. So maybe there's some confusion here as to what the author meant. The code below is for a hypothetical executable on a home computer which is why I'm using DC.W blocks to define areas of RAM.

main:
LEA DATA,A0
BSR SumUp
MOVE.W D0,SUM1  ;store in sum1
LSL.L #3,D0     ;multiply by 8
MOVE.L D0,MUL8

;coincidentally, A0 is already pointing to the start of the next 6 data entries
;so we don't actually need to modify it before repeating.
BSR SumUp     ;returns sum of $7 to $C in D0
LSR.W #2, D0
MOVE.W D0, DIV4

halt:
jmp halt 
;crash the cpu to prevent fallthrough into the subroutine
;you can replace this with your simulator or operating system's proper exit routine.
;I don't use easy68k so I don't know what that would be.


SumUp:
;input: A0 = source of data
CLR.L D0        ;ensure top 16 bits are empty, we'll need this later
MOVE.W (A0)+,D0
ADD.W (A0)+,D0
ADD.W (A0)+,D0
ADD.W (A0)+,D0
ADD.W (A0)+,D0
ADD.W (A0)+,D0
;now the sum of the six items is in D0
RTS


DATA:
DC.W 10,20,30,40,50,60
DC.W 10,20,30,40,50,60

SUM1:
DC.W 0   
;these zeroes are here to reserve space, they'll be overwritten
;with the results of the calculations

MUL8:
DC.L 0

SUM2:
DC.W 0

DIV4:
DC.W 0

puppydrum64
  • 1,598
  • 2
  • 15