Once you get the hang of addressing, everything else will start to fall into place.
Basically, any time you address memory, it will take the form [SOME VALUE], as I'm sure you already know. Without the []'s you'll simply be specifying an immediate.
The value between the []'s can contain any combination of the following three values:
1. A displacement. Basically any immediate value, for example:
Code:
mov WORD [0xB8000], 0x0741
You have the specify the operand size for the assembler to know the correct instruction to generate. Most of the time you don't have the specify it though. E.g.
Code:
mov ax, 0x0741
mov [0xB8000], ax
Does the same thing. But the assembler knows the size of the AX register, so the operand size (WORD) is implicit.
2. A register. You can treat the value inside any register as "pointer" to a memory location.
Code:
mov eax, 0xB8000
mov WORD [eax], 0x0741
This code does the exact same thing as above, but uses the value inside of EAX as a memory location. It's important to note that you have to use a 32 bit register (unless you're in Real\Long Mode) inside of the []'s. specifying a 16bit\8bit register will typically cause your assembler to spit out an error, although some might automatically assume you meant the 32 bit register (e.g. EAX instead of AX). It's also important to know that the just because you're using a 32 bit register as a memory address, doesn't mean the operand size is 32 bits. As you can see in the example above, the operation size is a WORD.
3. A register with a scale. Almost exactly the same as above, except that you can specify a "scale" which just multiples the value in the register by a certain amount. The scale can be 1, 2, 4, or 8 (only in long mode).
Code:
mov eax, 0x2E000
mov WORD [eax*4], 0x0741
Again, this is accomplishes the same thing as all of the other examples, since 0x2E000 * 4 = 0xB8000. Although it's not really used properly in this example, I think it's obvious that this addressing mode can be very useful for accessing arrays of WORDs or DWORDs.
Now as I said earlier, you can use any combination of the above three.
Code:
mov [eax + ebx*2 + 0xC0007C00], ecx
Is a perfectly valid instruction. One thing to note that the scale of one is implicit with all assemblers (that I know of), so
Code:
mov [eax + ebx], ecx
Is also a legal instruction. As I'm sure you can guess, in order to get the address to use, the processor simply adds everything up. So...
Code:
mov eax, 0xA0000
mov ebx, 0x2000
mov WORD [eax + ebx*4 + 0x10000], 0x0741
Produces the exact same result as all of the other examples.
Hope that helps to clear things up. I know it took me quite some time to fully grasp how to address memory in assembly.