First of all, none of the addressing modes in the original use an index register. [ebx+8] can (and will) use EBX as a base register, not an index register, because it can do that without a SIB byte in the machine-code encoding. So the addressing mode is base+disp8, so the encoding of the ModRM byte would be (in binary)
- Mod=01 (base+disp8)
- R/M = 011 (EBX)
- REG = 000 (EAX as the register destination)
So the ModRM byte would be 0x43, as per Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte, in Intel's instruction-set reference manual (Volume 2). (See the x86 tag wiki for links to the PDFs).
If there was a scale factor on EBX (like [ebx*2 + 8]), it would have to use the disp32 + index addressing mode. (See also x86 addressing modes).
Presumably you actually mean you can't use a displacement in your addressing mode.
In that case, the first instruction can't be the load, because you have to calculate the address in a register first. The question makes it easy for you, by later calculating the same ebx+8 value that you need as an address, using an ADD instruction. So you can just reorder, instead of having to modify EBX twice.
add ebx, 8
mov eax, [ebx]
add eax, 1
mov [ebx], eax
Or slower but fewer instructions:
add ebx, 8
add dword [ebx], 1 ; read-modify-write
mov eax, [ebx] ; and then reload
x86 has many weird and wonderful instructions, including XADD. You could even do this:
; LEA ebx, [ebx+8] might count as breaking the rules, even though it's not a load.
sub ebx, -8 ; use a different instruction just for variety.
mov eax, 1
xadd dword [ebx], eax ; read-modify-write, leaving the old value in eax
inc eax ; do the same add again, so the register matches what xadd put into memory.
But don't do this. XADD is slower than normal simple instructions. It's main purpose is multi-threaded synchronization. C++11's std::atomic::fetch_add is the same operation that XADD implements, so fetch_add() can compile efficiently on x86 to a lock xadd.