tags:

views:

644

answers:

3

So I decided to teach myself assembly language. I know on a very basic level how this stuff works, but I have never programmed so close to the hardware and I thought that I should definitely know this stuff. I was playing around with different registers and general syntactical stuff and I have realized that my program will not compile if I attempt to change the value of any segment register. Every article that I have found says that I can indeed change the value of at least 4 segment registers, so what gives?

I am really only interested in the why at this point, I don't have any real purpose in changing these addresses. I am sure this will be an easy one for you guys, so take it easy on me ;)

+3  A: 

Are you writing windows executables?

In protected-mode (Win32), segment registers are not used any more.

Reference:

Memory model is also drastically different from the old days of the 16-bit world. Under Win32, we need not be concerned with memory model or segment anymore! There's only one memory model: Flat memory model. There's no more 64K segments. The memory is a large continuous space of 4 GB. That also means you don't have to play with segment registers. You can use any segment register to address any point in the memory space. That's a GREAT help to programmers. This is what makes Win32 assembly programming as easy as C.

Blorgbeard
A: 

...I bought a textbook. It taught a little 16-bit architecture and then moved on to 32. I assumed that the examples were in 32-bit protected mode as well. OK, thank you very much Blorgbeard, I found some more recent documentation.

Ed Swangren
+2  A: 

You said you were interested in why, so:

In real mode, a segment is a 64K "window" to physical memory and these windows are spaced 16 bytes apart. In protected mode, a segment is a window to either physical or virtual memory, whose size and location is determined by the OS, and it has many other properties, including what privilege level a process must have to access it.

From here on, everything I say refers to protected mode.

There is a table in memory called the global descriptor table (GDT), which is where the information about these window sizes and locations and other properties are kept. There may also be local descriptor tables on a per-process basis, and they work in a similar way, so I'll just focus on the GDT.

The value you load into a segment register is known as a segment descriptor. It is an index into the GDT or LDT, with a bit of extra security information. Naturally if a program tries to load a descriptor which is outside the bounds of the GDT, an exception occurs. Also if the process does not have enough privilege to access the segment, or something else is invalid, an exception occurs.

When an exception occurs, the kernel handles it. This sort of exception would probably be classed as a segmentation fault. So the OS kills your program.

There's one final caveat: in the x86 instruction set, you can't load immediate values into segment registers. You must use an intermediate register or a memory operand or POP into the segment register.

MOV DS, 160  ;INVALID - won't assemble

MOV AX, 160  ;VALID - assembles, but will probably result in an
MOV DX, AX   ;exception, and thus the death of your program

I think it should be pointed out that the architecture allows for heaps of segments. But AFAIK, when it comes to the mainstream x86 operating systems, segment registers serve only a few purposes:

  • Security mechanisms, such as keeping user space processes from harming each other or the OS
  • Dealing with multiple/multi-core processors
  • A few other bits of x86 red tape

So really only a handful of segments (times the number of processors) are used, and only by the OS. Application programs can completely ignore the segment registers.

This is due to OS design, not to any technical limitations. There may be embedded operating systems that require user-space programs to work with the segment registers, though I don't know of any.

Artelius