booting FAT12 revisited

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.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

Octocontrabass wrote:
Schol-R-LEA wrote:

Code: Select all

        mov dx, bx
        [...]
        add di, dx
        add dx, bx
Instead of reading directory on each iteration, you're reading directory[i*(i+1)/2]. I'd get rid of DX and add BX to DI.


Oddly enough, I previously had it that way, but changed it while trying to find a way out of the problem. I'm not sure why I thought this was the better way, I was pretty tired at the point where I did that.

Octocontrabass wrote:You also jump to the RET instruction without popping the values you've pushed.

OK, I fixed both of those problems, but it still isn't finding the matching entry.

Code: Select all

seek_directory_entry:
    .dir_entry_test:
        push di
        push si
        push cx
        mov cx, filename_length
        repe cmpsb              ; does the directory entry match?
        pop cx
        pop si
        pop di
        je .entry_found
        add di, bx
        loop .dir_entry_test
        mov di, 0x0000          ; if not found, return 0
        ret
    .entry_found:
        ret
This is more or less where I'd started from the other day. What bothers me most is that it works with the mocked-up Root Directory, but not the real one. I have confirmed (to the best of my ability) that the real buffer is correct, and matches the mockup, so I can't understand why it isn't working the same way.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: booting FAT12 revisited

Post by Octocontrabass »

Schol-R-LEA wrote:I have confirmed (to the best of my ability) that the real buffer is correct, and matches the mockup, so I can't understand why it isn't working the same way.
How did you verify the buffer? Have you dumped all registers (including segment registers) at the point where you call this function to see if they match what you expect?
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: booting FAT12 revisited

Post by BenLunt »

Schol-R-LEA wrote:

Code: Select all

seek_directory_entry:
    .dir_entry_test:
        ...
        mov cx, filename_length
        repe cmpsb              ; does the directory entry match?
        ...
        je .entry_found
        add di, bx
I looked through your repo and I don't see where you have the actual binary file you are booting. Do you have it where we can download it and look? We are only getting one side here.

For example, what utility are you using to create the image? What utility writes to root directory for you? Are you using Linux and mounting the image to copy the secondary file to the image? If so, is Linux using a VFAT format? i.e.: adding long file names?

Anyway, the above code, cmpsb, assumes that the filename you are searching for *and* the directory entry are 8.3 formatted. i.e.:

Code: Select all

snd_stage_file  db 'STAGE2  SYS'
I have seen utilities incorrectly place

Code: Select all

snd_stage_file  db 'STAGE2',0,0'SYS'
in the directory entry.

Do you have a 1.44meg floppy image of the offending code so that we can "tear it apart"? Please excuse the expression.

Ben
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

BenLunt wrote:I looked through your repo and I don't see where you have the actual binary file you are booting. Do you have it where we can download it and look? We are only getting one side here.
I deliberately didn't bundle the image file into the Git repo (having added '*.img', '*.bin', and '*.qcow2' to the .gitignore file), as it gets automatically generated by the Makefile (which I posted earlier). I'll see about finding another place where I could save a copy to. However, I should mention that each of the test directories have their own copies of the image file, and each gets re-generated every time the it is built.
BenLunt wrote:For example, what utility are you using to create the image? What utility writes to root directory for you?
mkfs.msdos is the formatting utility. The full lines used to create and format the file are

Code: Select all

	dd if=/dev/zero of=boot.img count=1440 bs=1k
	mkfs.msdos -F 12 -n "VERBUM" boot.img
And yes, I now know that I could use mkfs.msdos to create the file itself, but I kept this as it's been for the time being.
BenLunt wrote:Are you using Linux and mounting the image to copy the secondary file to the image? If so, is Linux using a VFAT format? i.e.: adding long file names?
Yes to both, though I have made a point of sticking to all-caps 8.3 names.
BenLunt wrote:Anyway, the above code, cmpsb, assumes that the filename you are searching for *and* the directory entry are 8.3 formatted. i.e.:

Code: Select all

snd_stage_file  db 'STAGE2  SYS'
I have seen utilities incorrectly place

Code: Select all

snd_stage_file  db 'STAGE2',0,0'SYS'
in the directory entry.
I've checked the image file with a hex editor (the Emacs 'hexl-mode', specifically), and the file was saved with trailing spaces, not trailing nulls. still, it may be best if I used the full eight characters instead (e.g., 'STAGETWOSYS') rather than making assumptions, or having to count out the spaces by hand.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

I've come across another oddity. I have one test (fat_to_file_test.asm) which is able to find and load the second stage code by way of a mocked-up FAT, and display the code in hex. However, I then tried to see if it could then jump to that code, and the result was... nothing. It doesn't appear to jump to the second stage at all, or else the second stage code itself is buggy and doesn't print the simple message it's meant to.
Attachments
boot-image.zip
(3.74 KiB) Downloaded 71 times
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: booting FAT12 revisited

Post by Octocontrabass »

Schol-R-LEA wrote:or else the second stage code itself is buggy and doesn't print the simple message it's meant to.
It needs an ORG statement.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

Huh? It does have one already.

Code: Select all

%include "bios.inc"
%include "consts.inc"
%include "macros.inc"
%include "fat-12.inc"
%include "stage2_parameters.inc"

stage2_base     equ 0x0000            ; the segment:offset to load 
stage2_offset   equ stage2_buffer     ; the second stage into
                        
[bits 16]
[org stage2_base:stage2_offset]
[section .text]
The constant stage2_buffer is defined in fat-12.inc.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: booting FAT12 revisited

Post by Octocontrabass »

The ORG directive takes only one parameter, the offset. Specifying "org stage2_base:stage2_offset" is equivalent to specifying "org stage2_base". I'm not sure why NASM doesn't complain about invalid syntax here. Specifying "org 0" is equivalent to not specifying the origin at all, and I only looked at the binary so I didn't see that you already had one.

The NASM user manual recommends using user-level directives instead of primitive directives ("bits 16" instead of "[bits 16]"). I'm not sure exactly what's different between the two aside from the brackets, but it's probably a good idea to do what they say.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

Octocontrabass wrote:The ORG directive takes only one parameter, the offset. Specifying "org stage2_base:stage2_offset" is equivalent to specifying "org stage2_base". I'm not sure why NASM doesn't complain about invalid syntax here. Specifying "org 0" is equivalent to not specifying the origin at all, and I only looked at the binary so I didn't see that you already had one.
/headdesk

That did the trick. I can't believe I did that. The mocked up version now works.

I still need to get the 'official' version working, but now at least I know it can be made to work.
Octocontrabass wrote:The NASM user manual recommends using user-level directives instead of primitive directives ("bits 16" instead of "[bits 16]"). I'm not sure exactly what's different between the two aside from the brackets, but it's probably a good idea to do what they say.
I'll follow that advice, then.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

I finally got the whole thing working.

The answer came to me while I was re-checking the Intel manuals to see if I had misunderstood REPE CMPSB - which I had.

It turns out that I needed to use REPNE CMPSB, not REPE - the latter is REPeat until Equal, not repeat while equal as I expected it to be.

Such a simple, basic mistake... but the important thing is that I've got it working.

Thank all of you for your help, especially Octocontrabass and Ben Lunt. I could not have done this without you.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: booting FAT12 revisited

Post by Octocontrabass »

Schol-R-LEA wrote:It turns out that I needed to use REPNE CMPSB, not REPE - the latter is REPeat until Equal, not repeat while equal as I expected it to be.
No, you were right the first time, REPE is "repeat while equal". (Intel SDM volume 2B page 4-552.) There must be something else wrong.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

Octocontrabass wrote:
Schol-R-LEA wrote:It turns out that I needed to use REPNE CMPSB, not REPE - the latter is REPeat until Equal, not repeat while equal as I expected it to be.
No, you were right the first time, REPE is "repeat while equal". (Intel SDM volume 2B page 4-552.) There must be something else wrong.
OK, I misread what the manual (i386 Programmers' Manual) I was working from read, and you are right; what it says is, "Find nonmatching bytes in ES:[(E)DI] and [(E)SI]", i.e., repeat until it doesn't match.

However, for the time being, I am willing to work with the code as it is, since it actually does what I intended it to now. I can go back and work out the problem later.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: booting FAT12 revisited

Post by BenLunt »

Schol-R-LEA wrote:
Octocontrabass wrote:
Schol-R-LEA wrote:It turns out that I needed to use REPNE CMPSB, not REPE - the latter is REPeat until Equal, not repeat while equal as I expected it to be.
No, you were right the first time, REPE is "repeat while equal". (Intel SDM volume 2B page 4-552.) There must be something else wrong.
OK, I misread what the manual (i386 Programmers' Manual) I was working from read, and you are right; what it says is, "Find nonmatching bytes in ES:[(E)DI] and [(E)SI]", i.e., repeat until it doesn't match.

However, for the time being, I am willing to work with the code as it is, since it actually does what I intended it to now. I can go back and work out the problem later.
When you do get back to it, keep in mind that (most likely) the reason it works will be that the entry it found is the one and only entry, more importantly, the first entry. Therefore, it will work for now.
However, as soon as you use long file names *or* add another (valid) entry, it will no longer work.

Another reason it doesn't work correctly, at the moment, is your ES and DS segment values may be off. Remember that the CMPSx instruction uses the DS for the source operand and the ES for the destination operand. The DS can be overridden, but the ES can not.

Ben
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: booting FAT12 revisited

Post by Schol-R-LEA »

BenLunt wrote:When you do get back to it, keep in mind that (most likely) the reason it works will be that the entry it found is the one and only entry, more importantly, the first entry. Therefore, it will work for now.
However, as soon as you use long file names *or* add another (valid) entry, it will no longer work.
As it happens, mkfs.msdos adds a label entry as the first entry, so my file is technically the second entry. still, I should test this out by adding a dummy file before the actual second stage file. I'll post the results once I've tried that.

EDIT: I created a dummy text file comprised of several copies of "Lorem Ipsum", and altered the Makefile to automatically copy it to the mounted image before copying the second stage file. It still finds the second stage and jumps to it correctly. I'm still not sure what will happen when the second stage binary file get larger than one sector, though.
BenLunt wrote:Another reason it doesn't work correctly, at the moment, is your ES and DS segment values may be off. Remember that the CMPSx instruction uses the DS for the source operand and the ES for the destination operand. The DS can be overridden, but the ES can not.
I am explicitly setting ES == DS == CS, though, so I doubt that this is the cause, unless I am missing something.
Last edited by Schol-R-LEA on Thu Mar 11, 2021 3:22 pm, edited 2 times in total.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: booting FAT12 revisited

Post by Octocontrabass »

Is CS 0?
Post Reply