Ok here it is short sweet and to the the point: how do I get a asembly languige OS to reconise the floppy drive as A:/

Recommended Answers

All 7 Replies

This may seem simple, but the question carries with it more than you might suppose. First off, what do you mean by 'a: drive'? This may seem like an obvious point, but it isn't: the meaning of the drive lettering and so on is a feature of the OS itself, and no every operating system sees and uses drives the same way.

If the question is, 'how do you get the system to boot from the floppy drive?', then the answer is that it isn't a matter of the OS at all, but of the system CMOS settings. You'll need to go into the System Setup and make some selection regarding boot sequence (just where it is and what is it called will depend on the particular model of PC). Set the Floppy Drive (or FDD or whatever it is referred to) as the first boot device, and you should be able to at least get started.

Hi,

You can just change the Boot Sequence in order to show OS FLoppy Drive as A:/.You can change boot sequence through Bios Setup Hardware configuration.You can enter boot sequence either by pressing F10 or Delete while rebooting your system and change the settings and make floppy disk as primary IDE and save changes and restart your system it will boot from floppy drive A:/.

I have gotten much help from Schoil on the file matter I just want see how hard it is to get it to reconise a drive as a letter like DOS does it reconises it as A:/ (or is it \ I can never remember) like i I am making a OS get it to reconise the floppy drive as A:/ or \ wether or not I'll use that info is a different question.

I'm still not certain what you mean by 'recognizing' the drive as A:\ (the backslash is the DOS and Windows directory indicator; it's in Unix and Linux that it is the forward slash). A: is just a name which the OS assigns the drive; it is up to you whether or not to do the same, or use some completely different scheme if you'd prefer.

Let's look at this operationally: what is it you want the OS to do? Are you looking for it to put an A:\> prompt after loading? Do you want to know how the OS can read the drive with the path rooted at A:\ and find a file there? What behavior are you looking for?

Have you made any progress on this? Could you explain what you're trying to get the computer to do?

Sorry got caught up in real life... Um so yes, how would I do that; assine a drive a letter. Oh and the os is comeing along, slowly coughschoolcough.

as schoil pointed out, it sounds like you're not really clear on exactly how disk access works. there isn't some special CPU instruction that magically creates A:\ or anything like that. the easiest way to go about actually reading data off the disk is to use the BIOS routines for disk access on interrupt 13h.

it gets far more complicated from there. you need to parse the file system on the disk next. FAT is going to be the easiest file system out there to work with. in my OS, the first floppy drive is identified by the string "fd0:"

if you want to have a look at my disk.c file to give you an idea of how FAT can be implemented, i am pasting the code here for you. i know it's not assembly, but you can see how the basics work.

note that this code does not write files yet, and it's currently limited to the root directory. much of the could could be written better, but it's still very much a work in progress. this DOES work in the context of my OS though.

the OS is called MT86.. it's a 16-bit real-mode multitasking OS. it currently has functional virtual terminals, process forking, signalling, inter-process communication, and more.

i use the old Borland Turbo C++ 3.0 compiler, and simply compile it in tiny mode then exe2bin it, have another utility i wrote to make a bootable floppy image from that bin output and a custom asm bootloader i wrote.

#include <stdio.h>
#include <bios.h>
#include <mem.h>
#include "stdint.h"
#include "config.h"
#include "mt86.h"

//#define HDD_CACHE_SIZE 512

#define CLUST_OFFSET(x,y) (fat[x].offset+(fat[x].bytesperclust*(uint32)y))

extern uint16 curtty, maintty, debugtty;
uint8 hdcount = 0, partcount = 0;

struct structpart {
    uint8 status;
    
    uint8 f_head;
    uint8 f_sect_cyl;
    uint8 f_cyl;
    
    uint8 type;
    
    uint8 l_head;
    uint8 l_sect_cyl;
    uint8 l_cyl;

    uint32 f_lba;
    uint32 sect_count;
};

struct structmbr {
    uint8 dummy[446];
    struct structpart part[4];
    uint8 sig[4];
} mbr[4];

struct structdiskparm {
    uint32 sects;
    uint32 cyls;
    uint32 heads;
    uint32 totalsects;
    uint8 exists;
} diskparm[0x84];

struct structbpb {
    uint8 jump[3];
    uint8 oem[8];
    uint16 bytespersect;
    uint8 sectsperclust;
    uint16 reservedsects;
    uint8 numfats;
    uint16 maxroot;
    uint16 totalsects16;
    uint8 media;
    uint16 sectsperfat;
    uint16 spt; //sectors per track
    uint16 heads;
    uint32 hiddensects;
    uint32 totalsects;
};

struct structfat {
    struct structbpb bpb;
    uint8 exists;
    uint32 offset; //byte offset to BPB relative to start of disk
    uint32 fatloc; //byte offset to FAT #1 relative to start of disk
    uint32 root; //byte offset to root directory relative to start of disk
    uint32 data; //byte offset to data relative to start of disk
    uint8 drive; //what drive is this partition on?
    uint32 bytesperclust;
    uint8 name[6]; //device name, i.e. hd0p0
} fat[18];

struct structprocdisk {
    uint8 curpart;
    uint8 curpath[32]; //increase later
} procdisk[MAX_PROCS];

struct structdirentry {
    uint8 name[11];
    uint8 attr;
    uint8 reserved;
    uint8 tenth; //creation time in tenths of a second
    uint16 create_time;
    uint16 create_date;
    uint16 accessed;
    uint16 clust_high; //only used with FAT32
    uint16 modify_time;
    uint16 modify_date;
    uint16 clust;
    uint32 size;
};

struct structfile {
    uint8 used;
    uint8 partition;
    uint8 name[12]; //big enough for 8.3 and a null
    uint8 path[32];
    uint32 f_clust; //first cluster
    uint32 cur_clust;
    uint32 size;
    uint32 pos;
    struct structdirentry direntry;
    uint32 entryoffset;
} file[MAX_FILES];

uint8 hdd_sect_buf[4][512];
uint32 hdd_last_sect[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };

uint8 fdd_sect_buf[2][512];
uint32 fdd_last_sect[2] = { 0xFFFFFFFF, 0xFFFFFFFF };

extern int8 *msg;

uint32 chs2lba(uint8 drive, uint32 cyl, uint32 sect, uint32 head) {
    return(((cyl*(diskparm[drive].heads+1))+head)*diskparm[drive].sects+sect-1);
}

uint8 disk_reset(uint8 drive) {
    uint8 result;
    
    asm {
        xor ah, ah
        mov dl, drive
        int 0x13
        mov result, ah
    }

    if (result) {
        sprintf(msg, "[KERNEL] Error during reset of disk drive %02Xh\r\n");
        ttyprint(debugtty, msg);
        return(1);
    }
    return(0);
}

uint8 disk_read_sect(uint8 drive, uint32 lba, uint32 dst, uint8 count) {
    uint8 retry;
    uint8 sect, head;
    uint16 cyl, i, j, k, l;
    union REGS inregs, outregs;
    struct SREGS segregs;

    if ((drive>=0x80) && (lba==hdd_last_sect[drive&0x7F])) {
        i = _CS;
        j = &hdd_sect_buf[drive&0x7F][0];
        k = dst>>16;
        l = dst&0xFFFF;
        asm {
            pushf
            cli
            cld
            mov ax, i
            mov ds, ax
            mov si, j
            mov ax, k
            mov es, ax
            mov di, l
            mov cx, 256
            rep movsw
            popf
        }
        return(1);
    } else if ((drive<2) && (lba==fdd_last_sect[drive])) {
        i = _CS;
        j = &fdd_sect_buf[drive][0];
        k = dst>>16;
        l = dst&0xFFFF;
        asm {
            pushf
            cli
            cld
            mov ax, i
            mov ds, ax
            mov si, j
            mov ax, k
            mov es, ax
            mov di, l
            mov cx, 256
            rep movsw
            popf
        }
        return(1);
    }
    
    cyl = lba / (diskparm[drive].sects*(diskparm[drive].heads+1));
    head = (lba / diskparm[drive].sects) % (diskparm[drive].heads+1);
    sect = (lba % diskparm[drive].sects)+1;

    for (retry=0; retry<10; retry++) {
        inregs.h.ah = 0x2;
        inregs.h.al = count;
        inregs.h.ch = cyl&0xFF;
        inregs.h.cl = sect | ((cyl>>8)<<6);
        inregs.h.dh = head;
        inregs.h.dl = drive;
        if (drive<2) {
            //segregs.es = dst>>16;
            //inregs.x.bx = dst&0xFFFF;
            //int86x(0x13, &inregs, &outregs, &segregs);
            //if (!outregs.x.cflag) return(1);
            segregs.es = _CS;
            inregs.x.bx = &fdd_sect_buf[drive][0];
            int86x(0x13, &inregs, &outregs, &segregs);
            if (!outregs.x.cflag) {
                i = _CS;
                j = &fdd_sect_buf[drive][0];
                k = dst>>16;
                l = dst&0xFFFF;
                asm {
                    pushf
                    cli
                    cld
                    mov ax, i
                    mov ds, ax
                    mov si, j
                    mov ax, k
                    mov es, ax
                    mov di, l
                    mov cx, 256
                    rep movsw
                    popf
                }
                fdd_last_sect[drive] = lba;
                return(1);
            }
        } else if (drive >=0x80) {
            segregs.es = _CS;
            inregs.x.bx = &hdd_sect_buf[drive&0x7F][0];
            int86x(0x13, &inregs, &outregs, &segregs);
            if (!outregs.x.cflag) {
                i = _CS;
                j = &hdd_sect_buf[drive&0x7F][0];
                k = dst>>16;
                l = dst&0xFFFF;
                asm {
                    pushf
                    cli
                    cld
                    mov ax, i
                    mov ds, ax
                    mov si, j
                    mov ax, k
                    mov es, ax
                    mov di, l
                    mov cx, 256
                    rep movsw
                    popf
                }
                hdd_last_sect[drive&0x7F] = lba;
                return(1);
            } else hdd_last_sect[drive&0x7F] = 0xFFFFFFFF;
        }
    }
    return(0);
}

uint16 disk_read(uint8 drive, uint32 offset, uint8 far *dst, uint16 len) {
    uint8 readbuf[512];
    uint16 i = 0, j, k, l, read = 0;
    uint32 cursect, lastsect, remain;

    lastsect = (offset/512)-1; //actual value doesn't matter, we just need lastsect to differ from cursect on first loop iteration
    while (len>0) {
        cursect = offset/512;
        remain = offset%512;
        if (cursect!=lastsect)
            if (!disk_read_sect(drive, cursect, FARPTR(_CS, &readbuf[0]), 1)) {
                sprintf(msg, "[KERNEL] Error reading from LBA sector %lu on drive %02Xh\r\n", cursect, drive);
                ttyprint(debugtty, msg);
                return(read);
            }
        lastsect = cursect;
        dst[read++] = readbuf[remain];
        offset++; len--;
    }
    return(read); //return bytes read count
}

void enum_parts(uint8 drive);
void init_disk() {
    uint8 curdrive;
    union REGS inregs, outregs;
    struct SREGS segregs;
    
    hdcount = peekb(0x40, 0x75);
    sprintf(msg, "%u total.\r\n", hdcount);
    ttyprint(maintty, msg);

    for (curdrive=0x80; curdrive<(hdcount|0x80); curdrive++) {
        sprintf(msg, "    hd%u: ", curdrive&0x7F);
        ttyprint(maintty, msg);
        
        if (!disk_reset(curdrive)) {
            inregs.h.ah = 0x08;
            inregs.h.dl = curdrive;
            int86x(0x13, &inregs, &outregs, &segregs);
            
            if (outregs.x.cflag) {
                ttyprint(maintty, "Error on parameter check!\r\n");
                diskparm[curdrive].exists = 0;
            } else {
                diskparm[curdrive].exists = 1;
                diskparm[curdrive].cyls = (uint32)outregs.h.ch | ((uint32)(outregs.h.cl&0xC0)<<2);
                diskparm[curdrive].sects = (uint32)(outregs.h.cl&0x3F);
                diskparm[curdrive].heads = (uint32)outregs.h.dh;
                diskparm[curdrive].totalsects = (diskparm[curdrive].cyls+1)*(diskparm[curdrive].heads+1)*diskparm[curdrive].sects;
                sprintf(msg, "%lu cyls, %lu heads, %lu sects (%lu MB)\r\n", diskparm[curdrive].cyls+1, diskparm[curdrive].heads+1, diskparm[curdrive].sects, (diskparm[curdrive].totalsects*512)>>20);
                ttyprint(maintty, msg);

                if (!disk_read_sect(curdrive, 0, ((uint32)_CS<<16)|(uint32)&mbr[curdrive&0x7F].dummy[0], 1)) {
                    ttyprint(maintty, "Read error!\r\n");
                } else {
                    /*sprintf(msg, "\r\n [DEBUG] Hex dump of partition table on hd%u:\r\n", curdrive&0x7F);
                    ttyprint(maintty, msg);
                    hexdump((uint8 far *)(((uint32)_CS<<16)|(uint32)&mbr[curdrive&0x7F].part[0]), 64);
                    ttyprint(maintty, "Press any key to resume boot process...");*/
                    enum_parts(curdrive&0x7F);
                }
            }
        }
    }
    ttyprint(maintty, "\r\n");
}

void enum_parts(uint8 drive) {
    uint16 i, j, k, l, m, bits;
    uint8 tempdata[512];
    for (i=0; i<4; i++) {
        switch (mbr[drive].part[i].type) {
            case 0:
                break;
            case 1: //FAT12
            case 4: //FAT16 <32 MB
            case 6: //FAT16 (large)
                if (mbr[drive].part[i].type==1) bits = 12;
                    else bits = 16;
                sprintf(&fat[partcount].name[0], "hd%up%u", drive, i);
                sprintf(msg, "        %s: FAT%u volume (LBA %lu) ", &fat[partcount].name[0], bits, mbr[drive].part[i].f_lba);
                ttyprint(maintty, msg);
                fat[partcount].drive = drive|0x80;
                fat[partcount].offset = mbr[drive].part[i].f_lba*512;
                if (!disk_read(drive|0x80, mbr[drive].part[i].f_lba*512, (uint8 far *)FARPTR(_CS, &fat[partcount]), sizeof(fat[0].bpb))) {
                    ttyprint(debugtty, " [KERNEL] BPB read error\r\n");
                    break;
                }
                if (mbr[drive].part[i].type==4) fat[partcount].bpb.totalsects = fat[partcount].bpb.totalsects16;
                fat[partcount].fatloc = fat[partcount].offset + (uint32)fat[partcount].bpb.reservedsects*512;
                fat[partcount].root = fat[partcount].fatloc + ((uint32)fat[partcount].bpb.numfats*(uint32)fat[partcount].bpb.sectsperfat*512);
                fat[partcount].data = fat[partcount].root + (((((uint32)fat[partcount].bpb.maxroot*32)+511)/512)*512);
                fat[partcount].bytesperclust = (uint32)fat[partcount].bpb.bytespersect * (uint32)fat[partcount].bpb.sectsperclust;
                sprintf(msg, "[%s] %lu sects, %lu MB\r\n", &fat[partcount].bpb.oem[0], fat[partcount].bpb.totalsects, (fat[partcount].bpb.totalsects*512)>>20);
                ttyprint(maintty, msg);
                partcount++;
                break;
            default:
                sprintf(msg, "        hd%up%u: unrecognized partition type %02Xh\r\n", drive, i, mbr[drive].part[i].type);
                ttyprint(maintty, msg);
                break;
        }
    }
}

void mount_floppy(uint8 drive_id) {
    union REGS inregs, outregs;
    struct SREGS segregs;

        sprintf(msg, "    fd%u: ", drive_id);
        ttyprint(maintty, msg);

        if (!disk_reset(drive_id)) {
            inregs.h.ah = 0x08;
            inregs.h.dl = drive_id;
            int86x(0x13, &inregs, &outregs, &segregs);
            
            if (outregs.x.cflag) {
                ttyprint(maintty, "Error on parameter check!\r\n");
                diskparm[drive_id].exists = 0;
            } else {
                diskparm[drive_id].exists = 1;
                diskparm[drive_id].cyls = (uint32)outregs.h.ch | ((uint32)(outregs.h.cl&0xC0)<<2);
                diskparm[drive_id].sects = (uint32)(outregs.h.cl&0x3F);
                diskparm[drive_id].heads = (uint32)outregs.h.dh;
                diskparm[drive_id].totalsects = (diskparm[drive_id].cyls+1)*(diskparm[drive_id].heads+1)*diskparm[drive_id].sects;
                sprintf(msg, "%lu cyls, %lu heads, %lu sects (%lu KB)\r\n", diskparm[drive_id].cyls+1, diskparm[drive_id].heads+1, diskparm[drive_id].sects, (diskparm[drive_id].totalsects*512)>>10);
                ttyprint(maintty, msg);

                if (!disk_read_sect(drive_id, 0, ((uint32)_CS<<16)|(uint32)&mbr[drive_id].dummy[0], 1)) {
                    ttyprint(maintty, "Read error!\r\n");
                } else {
                    /*sprintf(msg, "\r\n [DEBUG] Hex dump of partition table on hd%u:\r\n", curdrive&0x7F);
                    ttyprint(maintty, msg);
                    hexdump((uint8 far *)(((uint32)_CS<<16)|(uint32)&mbr[curdrive&0x7F].part[0]), 64);
                    ttyprint(maintty, "Press any key to resume boot process...");*/
                    enum_parts(drive_id);
                }
            }
        }

    sprintf(&fat[partcount].name[0], "fd%u", drive_id);
    fat[partcount].drive = drive_id;
    fat[partcount].offset = 0;
    if (!disk_read(drive_id, 0, (uint8 far *)FARPTR(_CS, &fat[partcount]), sizeof(fat[0].bpb))) {
        ttyprint(debugtty, " [KERNEL] BPB read error\r\n");
        return;
    }
    fat[partcount].bpb.totalsects = fat[partcount].bpb.totalsects16;
    fat[partcount].fatloc = fat[partcount].offset + (uint32)fat[partcount].bpb.reservedsects*512;
    fat[partcount].root = fat[partcount].fatloc + ((uint32)fat[partcount].bpb.numfats*(uint32)fat[partcount].bpb.sectsperfat*512);
    fat[partcount].data = fat[partcount].root + (((((uint32)fat[partcount].bpb.maxroot*32)+511)/512)*512);
    fat[partcount].bytesperclust = (uint32)fat[partcount].bpb.bytespersect * (uint32)fat[partcount].bpb.sectsperclust;
    partcount++;
}

uint16 get_clust_val(uint8 part, uint32 cluster) {
    uint16 i, c;
    if ((fat[part].bpb.totalsects / fat[part].bpb.sectsperclust) < 4085) { //FAT12
        c = cluster + (cluster>>1);
        disk_read(fat[part].drive, fat[part].fatloc + c, (void far *)FARPTR(_CS, &i), 2);
        if (cluster&1) i = i >> 4;
            else i &= 0x0FFF;
    } else { //FAT16
        disk_read(fat[part].drive, fat[part].fatloc + (cluster<<1), (void far *)FARPTR(_CS, &i), 2);
    }
    return(i);
}

uint16 file_open(uint8 part, uint8 *path, uint8 flags) {
    uint16 i, j, k, l, m, handle;
    uint8 name[12], temp[12], cc;
    struct structdirentry entry;
    
    for (i=0; i<MAX_FILES; i++)
        if (!file[i].used) break;
    if (i==MAX_FILES) return(0xFFFF); //out of file handles, return error
    handle = i;
    
    for (i=0; i<11; i++)
        name[i] = 32;
    name[11] = 0;

    i = 0; j = 0;
    while (1) { //this loop normalizes the requested filename to match the entry format
        cc = path[i++];
        if (cc==0) break;
        if (cc=='.') j = 8; else {
            if ((cc>=97) && (cc<=122)) cc -= 32;
            name[j++] = cc;
        }
    }

    for (i=0; i<fat[part].bpb.maxroot; i++) {
        disk_read(fat[part].drive, fat[part].root + ((uint32)i*32), (uint8 far *)FARPTR(_CS, &entry), 32);
        //if (entry.attr&0x7F) { //attributes of 0x00 or 0x80 mean unused entry
            if (ismatchi(&name[0], &entry.name[0], 11)) {
                //ttyprint(0, msg);
                file[handle].used = 1;
                file[handle].partition = part;
                memcpy(&file[handle].direntry, &entry, 32);
                file[handle].entryoffset = fat[part].root + ((uint32)i*32);
                file[handle].f_clust = entry.clust;
                file[handle].cur_clust = entry.clust;
                file[handle].size = entry.size;
                file[handle].pos = 0;
                sprintf(&file[handle].name[0], path);
                sprintf(&file[handle].path[0], "%s:/", &fat[part].name[0]);

                return(handle);
            }
        //}
    }

    /*if (*hookbusy==0) {
        sprintf(msg, "File \"%s:/%s\" not found\r\n", &fat[part].name[0], path);
        ttyprint(curtty, msg);
    }*/

    return(0xFFFF);
}

void file_close(uint16 handle) {
    file[handle].used = 0;
}

void file_seek(uint16 handle, uint32 offset) {
    if (!file[handle].used) return;
    if (offset>=file[handle].size) return;
    file[handle].pos = offset;
}

uint32 file_get_pos(uint16 handle) {
    if (!file[handle].used) return(0xFFFFFFFF);
    return(file[handle].pos);
}

uint32 follow_clust_chain(uint16 part, uint32 first, uint32 count) {
    uint32 cluster, i;

    if (count==0) return(first);
    cluster = first;

    for (i=0; i<count; i++) {
        cluster = (uint32)get_clust_val(part, cluster);
        //disk_read(fat[part].drive, fat[part].fatloc + (uint32)cluster + ((uint32)cluster>>1), (void far *)FARPTR(_CS, &cluster), 2);
    }
    return(cluster);
}

uint32 file_get_size(uint16 handle) {
    if (!file[handle].used) return(0);
    return(file[handle].size);
}

uint16 file_read(uint16 handle, uint8 far *dst, uint32 offset, uint16 len) {
    uint16 i, j, k, l, m;
    uint16 curclust, lastclust, part, clustval, remain, ptr = 0, readcount, curread, totalread = 0;
    uint32 clustoffset;

    if (!file[handle].used) return(0);
    if (offset>=file[handle].size) return(0);
    if ((offset+(uint32)len)>file[handle].size) len = (uint16)(file[handle].size-offset);

    part = file[handle].partition;
    while (len>0) {
        curclust = (uint16)(offset / fat[part].bytesperclust);
        remain = (uint16)(offset % fat[part].bytesperclust);
        clustval = follow_clust_chain(part, file[handle].f_clust, curclust);

        readcount = (uint16)(fat[part].bytesperclust - (uint32)remain);
        if (readcount>len) readcount = len;
        curread = disk_read(fat[part].drive, fat[part].data+(fat[part].bytesperclust*((uint32)clustval-2))+(uint32)remain, (uint8 far *)((uint32)dst+(uint32)totalread), readcount);
        offset += (uint32)curread;
        totalread += curread;
        len -= curread;
        if (curread==0) {
            sprintf(msg, "[Kernel] Read error on %s\r\n", &fat[part].name[0]);
            ttyprint(curtty, msg);
            return(totalread);
        }
    }
    return(totalread);
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.