17.2 Memory Differences

17.2.1 Address are 32-bit

The address space is one, big, flat 32-bit space. When accessing memory, it needs to be accessed with 32-bit addresses. [DI] is as meaningless as [DL] was in real mode.

Caution: NASM will accept [DI] as a memory address without warning about its use! This can work, but only if the address fits in DI (eg, is in the first 64k). As this is not usually the case (especially when doing operations with large buffers), this doesn't usually work. Make sure to use the full 32-bit registers when doing address computations!

17.2.2 Any Register Can be Used to Access Memory

You can access memory like this [segment : any_32-bit_register + any_other_32-bit_register*(1/2/4/8) + constant] This means that this is all legal:

        mov al, [eax+4*ebx+12]       ; ds is the assumed segment
        mov ax, [gs:ecx-99]          ; ds, es, fs, and gs are ALL segment registers.
        mov edx, [myarray + ebx*4]   ; Locally multiply by four before to access array.

17.2.3 Segments are Completely Different

If you have a picture in your head of how segments work in real mode, great. If you know about how to calculate a linear address by multiplying the segment by 16 and adding the offset, great. You'll need this for the exam. You won't need this for protected mode. The segment registers in protected mode are now the selector registers. A selector is an index into a descriptor table. In the case of a single application program, it's an index into the Local Descriptor Table (LDT). The LDT is a table of (not suprisingly) descriptors. Descriptors hold information about a sub-region of the 4 Gigabyte 32-bit physical address space. The reason we need this table is because in protected mode, not every segment is the same size. Enough of theory; time to look at how this actually works, in the debugger.

17.2.3.1 Using the Debugger to examine the LDT

  1. Open some program in cv32 (like the basic program covered in Section 16.1.

  2. The help (ALT-H) says that to look at the Local Descriptor Table, type ALT-L, so do so.

  3. Look at the Code Selector (CS). Remember that the number here represents the Local Descriptor Table offset. Scroll down to this offset in the Local Descriptor Table window.

  4. It should say that it is a code selector that is read only. It probably starts at some huge linear starting address (0x837e5000) and is pretty big (0x0001ffff).

  5. Now look at the Default/Data Selector (DS) and its LDT entry.

  6. Looking at the LDT entry for DS, it should be 32-bit data which is both readable and writeable. It starts at the same address and is the same size as the Code Selector, strangely enough. Of course in the past MPs in ECE 291, we've set DS to point to the same place as CS. Note that the same thing is true here even though the selector registers themselves have different values.

17.2.3.2 How the Processor Handles Memory Accesses

To get the linear address for mov EAX, dword [DS:EBX], the processor looks in the Local Descriptor Table for DS's linear starting address. It then adds the offset (in this case the value in EBX) to get the linear address.

While the processor is doing this, it checks the offset against the segment length in the LDT. If the offset is "out of range" when it preforms the check, the processor causes a General Protection Fault and calls interrupt 13h. This interrupt goes to the operating system which promptly terminates the program for trying to access memory that it doesn't own. (This is one of the ways memory is protected in protected mode). "So why can't the program just go into the Local Descriptor Table and give the segment a huge length?" Programs are never allowed to deal with the Local Descriptor Table directly. They must request additional memory from the OS, and the OS changes the descriptor table. The OS also keeps track of what programs have what memory and shuts down misbehaving programs.

Tip: General Protection Faults are the primary cause of program crashes when programming in protected mode. When a fault occurs outside of a debugger, the program is terminated and information is printed to the screen that shows all the registers, the segments and their limits, and a stack trace. In a debugger, the debugger halts the program, highlighting the line that caused the error.

Once the processor has the linear address and has verified the offset is correct, it looks in the processor's Virtual Memory Page Table to get the physical address, which is what actually gets sent out on the bus. If the Page table says that the particular page required is not in physical memory, the processor causes a "Page Fault" and the operating system (in this case, Windows) will have to load it off of disk. (This procedure is often called swapping). Note that there are a few more levels of abstraction here than there were in real mode. ECE 291 doesn't cover Virtual Memory or swapping, so this paragraph really isn't that important to programming in ECE 291, except for the following:

Important: It's possible for memory areas accessible to the program to not actually be in memory at the time. This will be particularly important when writing interrupt handlers (also called interrupt service routines). The details surrounding ISRs in protected mode, using PModeLib, are covered in Section 18.7.