Think of each step instruction independently and see what it changes:
elauzel wrote
@SP // @0, M = RAM[0] = 256
This stores 0 in register A. Nothing more, nothing less.
elauzel wrote
D = M // D = RAM[0] = 256
Correct, D is assigned the value in RAM[0]. Assuming that RAM[0] contains 256, D becomes 256.
elauzel wrote
A = D - 1 // A = 256 - 1 = 255
Correct again.
elauzel wrote
AM = M - 1 // would this be A = RAM[0] = RAM[0] - 1, or A = RAM[255] = RAM[255] - 1 ?
This is the harder one. Let's first find out the M - 1 part. M here means take the value of RAM[A], that is RAM[255]. Let's say its value is x. M - 1 is evaluated to x-1. Think of it as if this is stored in some temporary register TMP.
Next it is the assignment. And it's ambiguous. It could mean
RAM[A] = x-1
A = x-1
or it could mean
A = x-1
RAM[x-1] = x-1
The second interpretation isn't very meaningful, as it would mean that AM=x will always make M[x] become x. This isn't very helpful, so it's better to implement the first interpretation.
You can test this, by entering your program in a asm file (but remove the spaces: it's D=M, not D = M, etc.). Then load it in the CPU emulator, store some meaningful values in RAM and step over it. I chose to store 20 in RAM[0] and 13 in RAM[19]. This way I can see the relevant RAM will be visible without scrolling.
The meaning of "M" doesn't change (or changes just a little). It always denotes RAM[A]. The only difference is, that M in the DEST part of the instruction means storing the COMP value in that RAM register, while M in the COMP part means fetching the value from this RAM register.