CLR R2 ; "low"
MOV #50., R3 ; "high"
MOV 100, R4 ; just for speed (you didn't have to do this for the exam)
LOOP: MOV R2, R0
ADD R3, R0
CLR R1
DIV #2, R0 ; "mid"
; address calculation (this can be optimized)
MOV R0, R1
ADD R0, R1 ; i.e. R1 <- [R0] * 2
ADD #500, R1 ; or use CMP R4, 500(R1) instead of next line
CMP R4, @R1
BEQ END ; "mid" already in R0
BLT TOOLOW
MOV R0, R3
INC R3 ; low := mid + 1
BR CONT
TOOLOW: MOV R2, R3
CONT: CMP R3, R2
BGT LOOP
MOV #-1, R0
END: HALT
In practice, I would personally optimize the address calculation by, basically, not dividing by two at that point so that it's still in bytes (this is just a coincidence, that the "/2" in taking the arithmetic mean is the same as the conversion between word and byte offsets, but these coincidences happen all the time and in machine-language programming we tend to take advantage of them), but you'd have to zero the low bit with "BIC #1, R0", and then you could use 500(R0) as the address. But I thought this was a bit too tricky to present as my official exam solution here.
The CLR R1 just before the DIV is required because the PDP-11 takes a two-word source for the numerator. You didn't have to do this for the exam. Actually I think it is probably the other way around: I think that R0 is probably the high word and R1 the low word. Although this strikes me as big-endian, it's how the MUL op works, or so I believe (I don't have personal experience with MUL and DIV on a PDP-11 and this issue seems to be ill-documented). Actually it would be easier to use an ASR (arithmetic right-shift).