These are a lot of questions at once, i'll answer at least some of them. But, please not, unless you're writing an assembler or disassembler yourself, you shouldn't really go into the gory details of every single bit. And unless you have done a lot of programming in assembler, and reading and understanding disassembled code, you shouldn't even try to write an assembler or disassembler yourself.
Don't misunderstand me, writing your own assembler can be an interesting and educational experience. But the gory details aren't first thing you should learn to understand the concept of a processor and its assembly language.
That out of the way:
It doesn't matter if the 16 bit displacement is signed or unsigned. If it overflows, it overflows, and it's always cut to 16 bit. So if you add offset
0xfff0 to address
0x1234, you'll get
0x1224 as result. It doesn't really matter if you interpret this as "
0xfff0 is equal to
-0x0010, so we subtract
0x1234" or "add
0x11224, and strip the overflow bit". Or, if you add
0x89ab, you get
0x11356 with the overflow bit stripped, to be precise. It doesn't matter if you take
0x89ab as (decimal)
-30293. The possible results -
-30293-30293=-60586 - do all have the same representation -
0x1356 - in 16 bit hex.
0b00 and R/M=
0b110 is just an indirect address.
mov cx, [1234h] and
mov cx, WORD PTR ds:0x1234 are two ways of writing the same thing. Note i corrected your
cx; whether or not you use an 8-bit or 16-bit register is part of the instruction, not of the addressing mode. If you have a register, the size is clear from the register name, but in an instruction like
mov [1234h],5, you don't know if the 5 is a byte, word, or dword value.
mov word ptr ds:1234h, 5 makes this clear.
Yes, all addresses are relative to the chosen segment -
ds in most cases,
ss if you use
bp, and the given register if you use an explicit override prefix. Note there wasn't a way to index relative to
sp in 16 bit mode, and
bp, if used at all, was always the first register in
R1+R2 combinations, forcing
ss to be used with
bp. In 32 bit mode, more combinations are possible, and
[ebx+ebp] uses ds. (However, 32 bit mode also means protected mode, and in all but the most pathological cases, operating systems use the same selector values for
cs as well. See below).
[SS:BP+SI+10h], which means
(SS<<4 + BP + SI + 10h) on the address bus lines. Note that those 16 bit processors had 20 bits on the address bus, which means overflow could occur, and the overflow bit was cut off as well. So, FFF0:0010 and 0000:0000 are actually the same address on an 8086 -
00000 - since bit 20 from
100000 got cut off. On a 32 bit processor, this bit 20 actually exists. Which means some programs, that used that mechanism to obfuscate their copy protections, stopped working when the 80386 was introduced. Or would have, if IBM hadn't invented a mechanism around it - the nefarious A20 gate. Google for that if you're inclined to do so.
67h - ask someone else. Although i've been reading and writing assembler code for more than 20 years, i never had reason to learn the relation between hex bytes and processor instructions. See above. Well, i guess there are two exceptions:
INT3. And byte sequences like
50h 51h 52h 53h 54h are push-register instructions, which makes them useful for locating procedure starts.
In 32 bit modes, the displacements are just as "signed" or "unsigned" as in 16 bit modes. Just treat them as 32 bit values that get added, which might result in an overflow that's thrown away.
And of course, these values are considered relative to the "segment"s as well. Just that 32 bit implies protected mode, which means the segments are called selectors, have different semantics, and get generally ignored by most application programmers.
A word to segments, why they mattered, and don't (normally) matter any more:
At first, when the 8086 was introduced, it was meant to replace the older 8080 processor (and the Z80, which was from a different company, compatible to the 8080, but better and more successful). The 8080 had 64 KB at a maximum altogether, so programmers had to squeeze everything - code, data, stack - into those 64 KB, and most of the time, a part of these 64 KB was used by hardware, so you had even less.
When the 8086, and the segment registers, were designed, someone at intel probably thought "We're giving people much more space - 64 kb code AND 64 kb data AND 64 kb stack, so programs can be much larger; we can multitask between several programs, the operating system will manage the segment registers to assign space to each program, and every program can be so much bigger than today".
But in fact, programs got much larger quickly, so the idea "segment registers should concern the OS only" wasn't ever used. Instead, programs had to juggle segments on their own, which was a major PITA for everybody from compiler builders to application programmers, and everybody had to learn - and know - about them to get anything done.
When 32 bit processors started, with 4 GB addressable in a linear fashion, segments suddenly became big enough that application programmers didn't have to care about them anymore. These days, juggling segments and assigning them to memory maps is strictly the task of the operating system, and due to protected mode, programs couldn't change them even if they wanted. So, what most operating systems do is provide one single flat block of memory to the program, and have
ss map to that block identically. Your application just sees 4 GB of addressable memory (not all of that needs to be truly mapped to physical memory however), and it doesn't matter to the application anymore which segment registers it uses -
[DS:1234] is the same as
[ES:1234] is the same as
[SS:1234] is the same as
The exception to this is the new registers
GS, for example, Windows uses
FS for Structured Exception Handling, and Linux uses
GS for Thread local storage. These segments are NOT mapped to the standard 4 GB block, but an application won't notice, since neither of these registers is ever used without an explicit prefix. (Note
ES can not be used in the same way, since instructions like
ES:EDI by default).