Buffer not filled while reading disk in C/ASM, need help.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
psimonson1988
Member
Member
Posts: 40
Joined: Tue Jul 16, 2019 8:40 pm

Buffer not filled while reading disk in C/ASM, need help.

Post by psimonson1988 »

I've been working on a project from scratch using as little Assembly as possible. But, I can't seem to figure out why my function read_disk() isn't reading into the buffer in bx register. To me it looks okay, but when I display the sector in hex to the screen it's all zeroed (not loaded). But I did have it working on an old commit Feb 16th of this year. Tried everything I could think of that might be the issue and none of it fixed the problem. The buffer was still blank. Any help in resolving this issue would be much appreciated. Thanks in advance.

P.S.: If you need help finding where something is in the code let me know and I'll be happy to guide you to where it's located at.

My ASM/C Floppy OS (Hobby OS)

EDIT: I fixed the issue, but I don't know how. Was messing around with setting up registers inside stdio.h in setup(). Also, changing linker scripts and now it works. Like I said, though I'm not sure how I fixed it. But this I guess is solved. Thanks all for your insight it was helpful.
Last edited by psimonson1988 on Mon Feb 24, 2020 4:47 pm, edited 2 times in total.
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: Buffer not filled while reading disk in C/ASM, need help

Post by Klakap »

I didn't know your code as all, but if you want read/write to disc with int 0x13 you should use code like this:

Code: Select all

  mov ax, 0x1000  ;segment for data
  mov es, ax  ;set segment
  mov bx, 0  ;offset for data
  mov ah, 0x02  ;read function
  mov al, 0  ;number of loaded sectors
  mov ch, 0  ;cylinder
  mov dh, 0  ;head
  mov cl, 1  ;sector
  mov dl, 0x80  ;hard disc
  int 13h  ;read
Please, use that one head have 18 sectors and one cylinder have two heads 0 and 1. You can read very little part of disc.

But, if you work in C, I suggest you to write PIO driver for reading disc. You will can read all hard disc with it.

Code: Select all

//my PIO48 driver
uint32_t paralel_ata(uint32_t base, uint64_t sector, uint16_t number_of_sectors, uint32_t type, uint32_t memory_pointer) {
    uint16_t *buffer = (uint16_t *) memory_pointer;
    uint32_t cycle=0;
    uint32_t offset=0;

    //PIO48
    outb(base+2, (unsigned char)(number_of_sectors >> 8));
    outb(base+3, (unsigned char)(sector >> 24));
    outb(base+4, (unsigned char)(sector >> 32));
    outb(base+5, (unsigned char)(sector >> 40));
    outb(base+2, (unsigned char)number_of_sectors);
    outb(base+3, (unsigned char)sector);
    outb(base+4, (unsigned char)(sector >> 8));
    outb(base+5, (unsigned char)(sector >> 16));
    //type
    if(type==READ) {
    outb(base+7, 0x24);  //Send command read
    }
    else {
    outb(base+7, 0x34);  //Send command write
    }

    //wait for BSY clear and DRQ set
    cycle=0;
    for(int i=0; i<1000; i++) {
        wait(1);
        if( (inb(base+0x206) & 0x88)==0x08 ) {  //drq is set
            cycle=1;
            break;    
        }    
    }
    if(cycle==0) {  //Something is wrong
        if( (inb(base+0x206) & 0x01)==0x01 ) {  //bad block
            ata_error();   
        }
        return 0;
    }

    if( (inb(base+0x206) & 0x01)==0x01 ) {  //bad block
        ata_error();    
    }

	for(int i=0; i<number_of_sectors; i++) {
    	for (int j=0; j<256; j++) {
        	if(type==READ) {
            	buffer[offset] = inw(base + 0);
        	}
        	else {
            	outw(base + 0, buffer[offset]);
        	}
			offset++;
    	}
	}

    return 1;
}
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Buffer not filled while reading disk in C/ASM, need help

Post by PeterX »

In boot.asm the disk read code looks fine, so you already know how to do it.
But in disk.c I can't find any register being set. They are used like %ax, %al and so on.

Did I overlook something or did you miss that?
Octocontrabass
Member
Member
Posts: 5578
Joined: Mon Mar 25, 2013 7:01 pm

Re: Buffer not filled while reading disk in C/ASM, need help

Post by Octocontrabass »

psimonson1988 wrote:Any help in resolving this issue would be much appreciated.
Set a breakpoint on the INT 0x13 instruction and dump all of the registers (including segment registers) to see what values they have before the BIOS is called. Do all the registers (including segment registers) have sensible values? Check afterwards too, in case the BIOS is reporting an error but your code isn't recognizing it.

If you're a retro hardware enthusiast, you might want to keep in mind that the geometry for a floppy disk is not necessarily the same as the geometry of the floppy disk drive. (This is unlikely to be a concern if you're only using 1.44MB disks.)
PeterX wrote:But in disk.c I can't find any register being set.
This is handled by the constraints in the inline assembly. You can read about it in the GCC manual.
psimonson1988
Member
Member
Posts: 40
Joined: Tue Jul 16, 2019 8:40 pm

Re: Buffer not filled while reading disk in C/ASM, need help

Post by psimonson1988 »

Well bx is being set, that's why I can't figure out why it doesn't work anymore. It used to I haven't changed my disk functions all that much. If you clone that url with git and then check out the last commit on Feb 16th. That code works and I've compared the two and can't understand why the older one works and the new one does not.

Oh by the way, "a"(val), "b"(buffer), "c"((c << 8) | s), "d"((h << 8) | p->drive) is how you set ax, bx, cx, and dx in GNU inline assembly. Just in case you didn't know.
@Klakap Thanks for the suggestion and sample driver code.
@Octocontrabass Thanks for the debugging tip.

EDIT: What debugger can I use on a custom OS? bochs or gdb or ... ???
Post Reply