@Chris W
(Not that I was the one who made the original challenge, and not that portability was the point, but let's see if I can answer this).
Firstly I would say that if you are trying to port assembler from one instruction set to another then you should almost certainly be starting again from scratch. My comments on portability were aimed more at moving from one family member to another within an instruction set. A few years ago there was a trend for increasing pipe-line lengths and code that did this kind of thing tended to get caught out. Too clever for it's own good.
However to answer your contention I am not aware of any main-stream processors which don't have the ability to load from an address specified in a register. Assuming you can do this then you just have to load the register with the base address then add the offset, then load.
ie (in pseudo assembler)
Mov r1,x
Add r1,W
Ldr r2 from r1
Can you think of a sensible processor which is not able to do this?
To be honest if you are coding in assembler then I think most programmers would agree that a different set of rules should apply from those used in a higher level language. In C you can always manage a look-up table with arrays, and let the compiler find the best way to do it.
Nowadays even in embedded applications you should only rarely be venturing into assembler, and usually only then for horribly speed or space constricted bits of code.