Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

8086 OS-less programming; segmentation

Well folks, this is a hard-to-place question, as it deals with a lot of hardware specifics, so I had a thought to put it to EE.SE, but the primary focus of this is programming, so I decided to stick it here.

I've recently got a big blast of nostalgia (as well as itch to get back into CPU intrinsics), so I decided to homebrew a 8086 microcomputer board. Granted that I'm familiar with x86 assembly (to a degree, as you'll see) and I already know how to get my code on to the computer board, let's get to the actual problem. For the purposes of being informed, I'm using NASM although I'm not fully up-to-speed on its syntax yet.

Obviously, an 8086 working in The Mode (Real Mode not being called Real Mode yet) has the first 1,024 bytes separated aside at the beginning for 255 2+2 byte interrupt vectors, so the actual instruction listings start at 0x3FF.

The problem here is because of the quirks of the system's memory segmentation, as well as the fact that I might as well be writing a BIOS, from how the system is concerned. Do the segment registers have to be set, and if so, how do I determine what to put there? Suppose I'm using EEPROM or some form of Flash for my code storage, so I have something of the sort:

section .text
org 0x0000
    ; Interrupt vectors reserved
    ivt: times 1024 db 0
main:
    cli      ; Clear out interrupts because no addresses are defined yet
             ; Problems HERE.
             ; Set up interrupt addresses

I know that may be horribly-bad and most likely obviously-wrong syntax, but it illustrates the point I'm trying to make. Do I have to set the segmentation registers manually, via something like mov CS, blahblahblah, and if so, how do I determine the addresses the different segments/sections in my code body occur at?

The title of this question gives reference to the fact that although I've done a lot of Googling, I couldn't for the life of me find a reference to operating-system-less programming of an 8086. All the sources I could find assumed I was writing for a system already in place where the interrupt vectors and segments and such were already set up and figured out, whereas I'm trying to make a knockoff microcontroller that does everything from the ground up.

like image 814
ecfedele Avatar asked Mar 17 '23 12:03

ecfedele


1 Answers

The 8086 uses a very simple form segmentation where every memory reference is based off of one of the four segment registers, CS, DS, SS, or ES. That means segmentation is always used on every memory access whether it's explicit in the instruction or not. To resolve a memory reference the CPU multiplies the value in the appropriate segment register by 16 and adds it to 16-bit offset giving a 20-bit physical address. This is what's called real-mode segmentation in modern Intel processors.

The CS register determines the base of the code segment. All instruction fetches are done in this segment, at the offset supplied by the IP register. As Nathan Fellman's answer indicates CS:IP is loaded with FFFF:0000 during processor initialization, giving a stating physical address of FFFF0h, so you'll need to have an EEPROM or something at this address. As your question notes, you'll also probably also want some form memory at the beginning of the physical address space for the interrupt vector table.

Where you locate anything else is up to you. You'll want to load the DS register so it points to where want to store most of your data, as most memory operands use this segment by default. You'll probably also want to have a stack so you'll also need load SS (and SP) with a suitable value. You can load the same value into SS as DS if you want. The ES register doesn't need to be loaded with any particular value, as only a few instructions use it implicitly (MOVS, SCAS, CMPS). You'll probably want to it free to use as an "extra" scratch segment register to access regions of memory other than those referred by CS, DS, or SS.

Note that assumes that you have a real Intel 8086 or 80186 processor. If you actually have a 80286 or later processor that you only want to use in real mode then starting address will be different. If you have some sort of clone 8086 processor you should consult it's datasheet to see if it also does anything different.

like image 95
Ross Ridge Avatar answered Mar 27 '23 15:03

Ross Ridge