#Xiromos 16-Bit NASM OS
1 messages · Page 2 of 1
do you know kolibriOS or MenuetOS?
they are both also written entirely in assembly
i will ask tomorrow my informatik teacher if he is impressed or not
what is informatik called in english?
You can even still fuck this up in C if your not careful
Technology or information technology probably
Sorted to IT commonly
Well what progress do you have so far
And why do you want to impress the IT teacher
It's easier to track down in C but you don't manually perform operations on stack and shi
why not, i think he will be proud of me
I had some issues with spinlocks and unlocking before I did the assembly to swap stacks lol
Fucking nightmare are to debug
Also what can your progress do right now
some basic commands and two very cool programs
yeah, it isnt fun
don't dig yourself a hole too deep to climb out of
if you're genuinely locked down this path, this isn't the best place to share progress
Especially if you aren’t experienced enough to be diving deep into this rabbit hole
Because people will keep telling you best practices lol
even if the best practices are specifically what you're avoiding
cough
but yeah i think there are actually a few communities that appreciate these
look around for retro computing groups
As long as you know what your doing by avoiding it. Because you specifically want to and you know what you’re doing. And you have already taken the beaten path
I feel like that’s a pretty basic thing
Obviously you are welcome to be here @raven sierra
Etc etc
cmon lets not have a brick wall competition in this guy's thread D:

Fair fair
Though I am just giving forewarnings and recommendations less of being a brick wall lol
it gets to a point at times yknow >:P
Just saying stuff like “assembly is easier” is a clear misnomer and makes me think they need the advice
yeah i agree
i said stuff like that jokingly before but with what ive seen now some things are less funny
techno if you want to see for yourself, try developing your os without any more guides
Yup and this is why people say these things to people with these beliefs
As it’s hard to tell when it’s a joke
When people are serious

assembly is a ton of tedious work for a short lived spike of dopamine
Most projects start in C and then maybe micro optimize some routines in assembly anyways lol
Stuff like SIMD
Optimizations should only be done after profiling anyways
with all the assembly i did learn i just couldnt go without more for this next foundation
And where you can make a meaningful improvement over the compiler
Yeah because alot of this assembly isn’t real world assembly
When the normal assembly in C OSDev is very diffrent
i learned real world assembly after i got home from ikea
inline assembly is a different species for sure
It’s not bad for a lot of things tbh
Port portIO wrappers etc
sti/cli etc
swapgs
real world or real mode?
mhm
yes to both?
how do i run, if no one shows me how to walk?
everyone needs to learn the basics and then develop their own ideas
Doing assembly is running before trying to walk
Learning how to walk means learning general programming.
Once you have enough experience, you won't need anyone to tell you what to do.
The basics are normal programming on an existing OS, implementing various algorithms and data structures, familiarizing yourself with UNIX userspace, etc ...
Constantly following tutorials puts you what’s known in game dev as “tutorial hell” and it can be very hard to escape once your doing it
What do you mean by "tried"?
assembly is more fun
and also like ... knowing what compilers and linkers do
translating the programming language into machine code
A compiler does a lot more than that especially internally
What's the role of the linker here?
x16-PRos code?
just same functions
@echo granite's code
oh
true
but why did you make so much different subroutines
you could just let the user choose the color
I fixed this in the new dev version.
https://github.com/PRoX2011/x16-PRos/blob/dev/src/kernel/kernel.asm#L115
(i mean the programmer)
print_string_green:
mov bl, 0x0A
jmp print_string_color
; ------ Cyan ------
print_string_cyan:
mov bl, 0x0B
jmp print_string_color
; ------ Red ------
print_string_red:
mov bl, 0x0C
jmp print_string_color
; ------ Yellow ------
print_string_yellow:
mov bl, 0x0E
jmp print_string_color
isnt it still useless?
you could just do that:
mov bl, color
call print_string
or make a macro
yeaaah, that is right
print_string_cyan:
mov ah, 0x0E
mov bl, 0x0B
jmp print_char
;--red--
print_string_red:
mov ah, 0x0E
mov bl, 0x0C
jmp print_char
;--green--
print_string_green:
mov ah, 0x0E
mov bl, 0x0A
jmp print_char
;--yellow--
print_string_yellow:
mov ah, 0x0E
mov bl, 0x0E
jmp print_char
;--darkblue--
print_string_darkblue:
mov ah, 0x0E
mov bl, 0x01
jmp print_char
;--white--
print_string_white:
mov ah, 0x0E
mov bl, 0x0f
jmp print_char
;--dark-red--
print_string_darkred:
mov ah, 0x0E
mov bl, 0x04
print_char:
lodsb
cmp al, 0
je print_char_done
int 0x10
jmp print_char
print_char_done:
ret``` i did it like this
because you can then just type the color, instead of remembering the color code
useless
just use preprocessor consts
and i think this costs less memory
wdym
writing
%define MY_COLOR 0xab
and
mov bl, MY_COLOR
call print_string
is much better
hm, nah, there is no difference
there is
with your solution, you have 50 useless subroutines
for the same thing
with my solution, you only have 1 subroutine
and consts to easily pass colors
you can even write a macro
so you would end up with something like this:
PRINT_COLORED_STRING "Message", MY_COLOR
btw i didnt copy the code, i did it like this because wither.cpp suggested it
wtf are you saying
maybe your right
when did i told you to do that
you told me to do the code shorter, so i edited it a little bit
i never told you to keep your 50 subroutines
okay, but i wrote my code my own and didnt copied it from proX
so?
he said i copied his code
..and you indicated copyright, as required by the MIT license
assembly bootloader for 16bit FAT16
oh
I have one for FAT12, FAT16, and FAT32 I'm developing
oh wow, that is pretty cool
how do you develop this skill that you can implement things which are in a documentation?
reading comprehension?
there's a reason schools have English lessons
practice and experience programming and reading documentation
and I guess reading comprehension and logical thinking skills
well you have had plenty of time and experience learning judging by that code
you should be able to move just fine
besides, writing code independently gets you farther than any guide
true
cool
should i use LBA or CHS in my filesystem?
because i think LBA would be easier, but some tutorials recommend CHS, but i dont understand why
Isn’t LBA newer?
yes it is
Then why use CHS :p
CHS is used on hard disks because it uses tracks, cylinders, etc. LBA is newer and works easier, but i think it is designed for SSDs
No LBA very well works on hard drives
well, then i will use LBA
every computer made after 1994 supports LBA for hard drives
most tutorials are bad
floppy disks support CHS only tho
ohh, i see
nah, LBA predates SSDs by decades
this was a FAT12 tutorial
you should avoid tutorials
yes, im trying to understand this documantation https://elm-chan.org/docs/fat_e.html
Yes iPhone I would love to open this with retroarch 💀
what is that?
It’s a game emulator lol. I was just trying to open the document and my phone was being dumb
wtf
let techno work cmon don't bring it up again
where is a good space to load the FAT?
doesnt mikeos load it to 0x2000 or smth?
it's up to you
tbh, MikeOS isn't that great of a design
MS-DOS 1.0 is unironically superior
i have my kernel at 0x500 and my programs at 0x5000. maybe i should put it on 0x8000?
which FAT variant are you implementing?
I guess it'll need at most 128kB
so 0x8000 would be a good choice
asuming conventional memory goes all the way to 0xA000
which it often doesn't
cuz EBDA
also
why are you hard-coding program and FAT locations
its easier? and i dont have multitasking so hardcoding programs is okay i guess
What makes it easier?
you just can type in the adress and you dont have to calculate it
;BIOS disk read function
;bl = drive type
;ch = maximum cylinder number
;cl = maximum sector number
;dh = maximum head number
;dl = number of drives
;al = number of sectors
pusha
mov ah, 0x02
mov al, [RootDirSectors]
mov cl, 3 ;start sector
mov dl, [BS_DriveNumber]
mov bx, 0x8000
mov es, bx
int 0x13
popa
jc disk_read_error
ret``` is this a valid function to load the root directory?
subroutine*
and is your OS for 8086 only?
yes
what do you mean?
what you wrote is a subroutine
then you can't use pusha and popa
a subroutine is a point in a program you can jump to from anywhere and which optionnally has arguments and a return value
also a function does respect a call convention
DoSomething:
; ...
ret
this is a subroutine
oh, so i better add this function on top, right? without ret
does ot work then?
btw what is the difference betwenn int 0x13 ah=0x02 and ah=0x42?
0x2 writes on sectors, and 0x42 uses LBA instead of CHS
wdym
why would you remove the ret and put it on top
then it isnt a function anymore and it is wothout ret, so i can push the registers
0x02 doesnt write, it also reads, but different than 0x42
uh yeah 0x2 reads srry
but it uses CHS
why remove ret
thats stupid
just keep it how it is
it's not a function since it doesnt respect a clear call convention
alright
i dont really understand how to search for the kernel.bin file, does anyone has a tutorial on this topic?
Eh, that's a nitpick at best.
And also not how that term was universally used.
not necessarily
first, you can't assume you can read multiple sectors across track boundaries
also, you can't assume the FAT is only one sector
You mean scanning the root directory for a particular filename?
yes, exactly
I think you can figure it out on your own.
Start with this question: how is a FAT directory structured?
are you still using assembly only?
man, the os name 🙏
yes
why? are you gonna make a dos or something?
We have gone over this possibly like 5 times in this channel
I don’t think we can change the persons mind even if it’s not the best idea™ for them to do this
yes
There's no point in bringing this up again.
where do i have to put the kernel.bin on the disk when loading it with qemu?
where you want
format your disk image in fat16
how do i do that with qemu? i have a disk image
and then you can use mtools (for example) to copy the kernel on it
is it formatted in fat16?
no
thank you
np
cli
xor ax, ax
mov ds, ax ;start adress of the data segment
mov es, ax ;start point of the extra segment
mov ss, ax
mov sp, 0x7c00
sti
mov ax, 0x03
int 0x10
mov ax, 0x12
int 0x10
mov si, loading_str
mov bl, 0x0f
call print_start
;check if LBA is supported
check_lba_supp:
mov ah, 0x41
mov bx, 0x55aa
mov dl, byte [BS_DriveNumber]
int 0x13
jc .no_supp
mov bx, 1
jmp load_root
.no_supp:
mov bx, 0
jmp main
load_root:
;BIOS disk read function
;bl = drive type
;ch = maximum cylinder number
;cl = maximum sector number
;dh = maximum head number
;dl = number of drives
;al = number of sectors
mov ah, 0x42
mov al, [RootDirSectors]
mov cl, 3 ;start sector
mov dl, [BS_DriveNumber]
mov bx, 0x8000
mov es, bx
int 0x13
mov [LBA], bx
jc disk_read_error
;detect ram
clc
int 0x12 ;ax = memory in KB
jc ram_error
mov si, ram_ok
mov bl, 0x0a
call print_start
mov dx, [BPB_RootEntry]
search_kernel:
mov si, file_kernel_bin ;ds:si = name
mov cl, 11 ;length of name
cmp byte [es:di], ch
je kernel_error ;end of root directory
push di
repe cmpsb
pop di
je load_startCluster
add di, 32
dec dx
jnz search_kernel
mov di, [es:di+1Ah]``` hm
something is wrong
do i have to specify the LBA value in search_kernel?
you wrote the subroutine, you should know
what do you mean?
he means that you should know what to do since (he supposes that) you wrote that subroutine yourself
oh
do you have an idea why the load_root function doesnt work anymore?
if i change ah to 0x02 it works
but why not in 0x42?
you don't have a disk access packet (DAP) as i can see
LBA works differently than CHS
mov bx, 0x55aa
mov dl, [BS_DriveNumber]
int 0x13
jc disk_read_error``` i dont understand what i am doing wrong. I know that SeaBIOS supports EDD, but it shows a disk error
don't these things have documentation
they indeed do
sometimes reading it can surprisingly be helpful if you know where to look
but there are a lot of things bios-related that asking this place can't really solve
relying on the bios is also normaly not the best™ if you can help it
does the best™ ship with the gnu license
i am unsure
SeaBIOS supports 0x41
yeah bios support for EDD has been basically standard for a long time now
what's in BS_DriveNumber? should be 0x80 for 1st/only hard drive. if it's correct, is it where the assembler and linker think it is?
yes, BS_DriveNumber is 0x80
also, if i replace [BS_DriveNumber] with 0x80 it is not working too
ah!
i think i have to replace fda with hda right?
bruh it works...
yeay! 😄
what an embarassing mistake, but thank you for helping me
you're welcome 🙂 it's often useful to pretend you're describing the bug to someone else
it shows up stuff like this
it's called "ruber duck debugging" after someone said they keep a rubber duck on their desk and explain bugs to it 🙂
interesting
tbh that is a really good way to debug
it is the only way to debug
except for gdb
but in my case yes
because i dont understand gdb
i don't use gdb
oh nevermind i guess i do
but i usually just study my code and then manually check registers and memory if that fails
me too, if something doesnt work i first look, if the nasm compiler said something and then just study my registers and try different things
nasm is an assembler, not a compiler
its basically just a compiler for assembly
👍
a compiler converts high level code to lower level code, menawhile an assembler converts assembly code (which is low level) to machine code (which is also low level)
but who is compiling the low level code of the compiler to machine code?
iirc, a compiler for 2 that turns 1 language into another language at the same level is a transpiler 👍 (jk, binaries are not human readable)
thats the assembler
does it mean, a compiler has an inbuild assembler?
yes ofc
dont you know how GCC works?
no
gcc is quite modular
it commonly process your C files in 4 steps
preprocess (includes/macros...) (GCC) -> compile (to asm) (GCC) -> assemble (GNU ASsembler) -> link (GNU LD)
try passing an assembly file to gcc and see if it can compiles
wat
what extension did you use?
it should be .s or .S
using intel at&t syntax
gcc boot.s -o boot.bin like this?
supposedly
but i dont have a boot.s file
i thought we are talking about gnu as can compile assembly?
but i assume nasm syntax?
gcc test.o -o test it worked with this command
gcc doesn't support nasm syntax
.o files are not asm files
they are relocatable ELFs
yes
aka ET_RELOC, .so (shared objects) are usually ET_DYN
thats not true
if i set in my DAP first the offset and then the segment, the program doesnt work. but if i do it the other way around it works
btw do you have any tutorials how to load the kernel.bin file into memory in FAT16?
because im searching for hours now and i didnt find anything
find it and read it
how?
crawl the rootdir until you find the file
and once you found it, read it from the disk
do you think it is possible to make my own assembler?
sure
but the question is "why"
yes
I mean, try figuring that out yourself.
Because asking "are there any tutorials" will not get you very far in OSDev.
Back years ago when I first ever attempted it by looking at YouTube tutorials instead of just doing it etc etc and reading documentation
I would give up because all the tutorials ended super early and were generally of the dookie but category
db 0x10 ;size of packet (16 bytes)
db 0 ;always 0
dw 32 ;number of sectors to read
dw 0x0500 ;adress
dw 0x0000 ;offset
dq 9 ;LBA
main:
cli
xor ax, ax
mov ds, ax ;start adress of the data segment
mov es, ax ;start point of the extra segment
mov ss, ax
mov sp, 0x7c00
sti
;clear screen
mov ax, 0x03
int 0x10
;set video mode
mov ax, 0x12
int 0x10
mov si, loading_str
mov bl, 0x0f
call print_start
;lba extended mode
clc
mov ah, 0x41
mov bx, 0x55aa
mov cx, 0x0000
mov dl, [BS_DriveNumber]
int 0x13
jc error
cmp bx, 0xaa55
je load_root
mov si, no_supp
mov bl, 0x0c
call print_start
jmp halt
load_root:
;BIOS disk read function
;bl = drive type
;ch = maximum cylinder number
;cl = maximum sector number
;dh = maximum head number
;dl = number of drives
;al = number of sectors
mov ah, 0x42
mov si, dap
mov dl, [BS_DriveNumber]
int 0x13
jc error
;detect ram
clc
int 0x12 ;ax = memory in KB
jc error
mov si, ram_ok
mov bl, 0x0a
call print_start
xor dx, dx
mov dx, [BPB_RootEntry]
search_kernel:
push cx
mov cx, 11 ;length of file name, needed for 'rep'
mov si, file_kernel_bin ;ds:si = name
cmp byte [es:di], 0
push di
rep cmpsb
pop di
je load_startCluster
pop cx
add di, 32
dec dx
jnz search_kernel
jmp error2
``` I dont understand why kernel.bin isnt found. Maybe the extra segment is wrong set, but what do i have to set it?
osdev.wiki said i should swap in the DAP the segment and the offset, but that doesnt work
yes, you should
offset comes first, then segment
if it doesn't work, then something else is wrong
yes
it doesnt work
hmm
maybe my build script is wrong?
nasm -f bin kernel.asm -o kernel.bin
dd if=/dev/zero of=disk.img bs=1M count=16
mkfs.fat -F 16 disk.img
dd if=boot.bin of=disk.img conv=notrunc
#dd if=kernel.bin of=disk.img bs=512 seek=18 conv=notrunc
mcopy -i disk.img -D o kernel.bin ::/KERNEL.BIN
qemu-system-i386 -hda disk.img -m 2M```
that looks fine
instead of dd i use mcopy
when i start the script, it shows an error that it couldnt initialize ::
what does that mean?
init :: non DOS media
is that your entire file?
do you have a BPB
of course
at the beginning of your bootsect
after the first 3 bytes?
and is this BPB valid
can you upload what you currently have to github?
bits 16
start:
jmp main
;=============FAT16==============================
BPB_OEM db "MSWIN4.1" ;OEM identifier (can be ignored)
BPB_BytesPerSec dw 512 ;sector size in bytes
BPB_SectorsPerCluster db 8 ;amount of sectors in one cluster
BPB_ReservedAreaCnt dw 1 ;number of sectors in reserved area(0 = bootsector)
BPB_NumberOfFATs db 1 ;if a sector in FAT area is damaged, data is not lost, duplicated to another FAT
BPB_SectorsPerFAT dw 8
BPB_RootEntry dw 512 ;defines number of directory entries in root directory
BPB_TotalSectors dw 32768 ;number of all sectors
BPB_Media db 0xF8 ;media descriptor byte, F8 is commonly used for partitioned disks
BPB_FATSz16 dw 8 ;number of sectors, occupied by a FAT
BPB_SectorsPerTrack dw 32
BPB_NumberOfHeads dw 8
BPB_HiddenSectors dd 0 ;number of sectors before a partition,(eg. if this would be on the second partition with 4096 sectors before it, number would be 4096)
BPB_TotalSectors32 dd 0 ;0 because i already have BPB_TotalSectors
BS_DriveNumber db 0x80
BS_Reserved db 0
BS_BootSignature db 0x29
BS_VolumeID dd 0x00000000
BS_VolumeLabel db "Xiromos "
BS_FileSystemType db "FAT16 "
;sector 0 = boot
;sectors 1-8 = FAT
;sectors 9-40 = root directory
;sector 41++ = data
FATStartSector dw 1
FATSectors dw 8
RootStartSec dw 9
RootDirSectors dw 32 ;(512 × 32)
DataStartSector dw 41 ;41 ReservedSectors + (NumOfFATS * FATSz16) + RootDirSectors
DataSectors dw 32727 ;32768 - 1 - 8 - 32
;FAT16
CountOfClusters dw 4090```
you need nop after jmp main
because the bpb must start after the first 3 bytes of the boot sector
okay
jmp main is only 2 bytes
also, you're overwriting the BPB
you should avoid that
how?
your format your disk after writing the bootsector to it
like this:
so it is erased
nah, formatting afterwards will erase the bootsector
i.e. only overwriting the parts that aren't in the BPB
no
oh yes im just stupid
it worked, but now the load_root function sets a carry flag
last time when it did so the problem was, that it was a floppy disk, but now it is a hard disk
nevermind, ah=0x41 and int 0x13 sets the carry flag
If you don’t like the flag being set or if you need to use it later etc why not save and restore it?
Or just unset it manually after?
no, if the carry flag was set that means there was an error while reading the disk
Ahh
nasm -f bin kernel.asm -o kernel.bin
dd if=/dev/zero of=disk.img bs=1M count=16
mkdosfs -F 16 disk.img
dd if=boot.bin of=disk.img bs=1 count=11 conv=notrunc
dd if=boot.bin of=disk.img bs=1 count=450 seek=62 skip=62 conv=notrunc
mcopy -i disk.img -D o kernel.bin ::/KERNEL.BIN
qemu-system-i386 -hda disk.img -m 2M``` is this okay so?
it isnt showing errors anymore
if i comment out dl when checking if the BIOS supports EDD, the carry flag isnt set anymore but instead it is set in the load_root function
very interesting
and if i comment out dl in the load_root function, only the string "Loading Kernel..." is shown
that means the whole program refuses to work
but the problem cant be with the stack
ask ai
gemini, chatgpt
they're pretty good at answering questions
(unlike this community lol)
its fine asking ai aslong is your not just putting your brains away and letting AI do all the work
its basically the same as looking at tutorials anways
well i cant
it might just be a skill issue but
without ai i probably would have quit a long time ago
(note: most people have skill issue)
nah
idk but i do have a skill issue
maybe the use of AI prevents you from resolving that skill issue
because you can only build skill by practice
well i am practicing?
and im not just turning my brain off and let ai do all the work
and rn im using ai a lot less then when i started
then what do you use AI for?
asking questions lol
well if i "figure it out my self", ill try to use google search, then ill just get either no result, or a website thats like 20 years old out of date
or ill find a reddit post with someone like you responding
someone like me?
people who just say "figure it out by your self"
yea it might just be a skill issue but im pretty sure most people do have skill issue
I told him that specifically for the FAT16 question
because I know he has all the ingredients necessary to answer the question
and doesn't need AI or tutorials
oh ok mb iguess
and this is exactly the kind of problem any sufficiently experienced programmer has to be able to solve
or at least any programmer who wants to do OSDev
i wonder is this still being actually worked on
yes
or is it an infinite argument over the OP's questionable choices
no
ohok
not anymore i guess
like
if I give you the FAT spec
you should be able to produce a program that reads out a file in the root directory
well i kinda cant. i usually learn by reading examples and stuff
(again, it might just be me having a skill issue)
What would exactly be the roadblock?
Because learning involves generalizing to examples you haven't seen yet.
hmm i havent really tried this
but i havent written any sort of FS driver before
ive tried before but i doesnt really know where to start
currently im just using other libraries to does the fs stuff
just the steps to read a file sequentially from start to finish, not a complete FS driver
given you already know how to read blocks from disk
that's my point
lol me too
Knowing how to google and find things is also quite an important skill
I’ve found some crazy ass docs that can help pretty well if you know how to use a search engine
true
btw i use ai to ask questions like: what does this word mean? or what does this instruction do? something like that
Don’t ask AI anything especially if you don’t know what your doing
I’m gonna tell you this but I started programming before AI
When it hit I ended up getting a free thing of copilot for VScode
It severely stunted my growth as a programming
You do not learn at all when using AI
I rarely use it these days except for boilerplate etc and finding stupid bugs
But 99% of the time I’m good enough to find it and fix it myself :p
well i didnt start programming with ai so i cant tell
i mainly just ask ai about what does x linux syscall do
because i dont feel like reading man pages from the 1990s
imo asking these is fine
i didnt either :p
i started without AI
then used it. and noticed i was being stunted
the man pages are very well not from 1990 :p
No they aren’t. That website has tons of man pages for tons of things
And they offten come up on searches
Learn to use a search engine and RTFM
tho imo ai results are usually better then man pages
although they can hallusinate and respond with random bs
Exactly. Which is why you read the actual manual and specs
It’s not rocket science and you prove my point on the AI
So many people put a good bit of effort into making well made manuals. Even ones from the “90s”are perfectly well made
?????????
I wonder where the ai got the information from 🤔
yea but if ai is better i am gonna use it
ai can summerize it a lot better
then man pages
who needs a summery when you can just read the whole thing and it be correct?
man pages aren't a 20,000 word book
well it kinda is to me
anyways im gonna keep using ai for it because its just better at this
but it literalty is not?
idk it might be a skill issue
Man pages are incredibly useful
man pages literally document, AI can make mistakes and hallucinate and YOU without real knowledge may apply something wrong.
You're absolutely right! I made a mistake 😅
This command 👉 sudo rm -fr /* does NOT delete the French language pack.
My mistake! But honestly.. — the way you picked up the mistake truly shows your technical knowledge.
sounds like gpt
That's the whole point
Aswell again like I said before. Using AI at all is still going to stunt your growth somewhat to some extent even if you don’t think you’re relying on it.
And I have seen your code Elyssa and uhh yeah I can see a lot of issues with it at times. And I’m not surprised given your takes here
guys
why is ah=0x41 int 0x13 working when i put 0x80 manually, but doesnt work when i put BS_DriveNumber in there???
What value do you have stored in BS_DriveNumber?
0x80
i definded it after the BPB, but i also do ah=0x08 int 0x13 to get drive parameters and then move into BS_DriveNumber dl
have you checked it's still 0x80 in the final image using a hex editor
yes, it is still 0x80
there is this long row of zeros because of hiddenSectors and TotalSectors32 and then there is the 80
in the 2. line
its position looks off by two bytes
why that?
maybe i should remove the TotalSectors32
no, i cant
then it will not boot
i dont understand
Why is the number of FATs one?
This shouldn't be there.
ohh
here the sectors per FAT are defined in the bpb
and this too
and my bootloader isnt working anymore
but in the FAT documentation there was no SecPerFAT
very interesting
wait, im stupid, i already have FATSz16
so this is not nessecary
but why isnt it working anymore when i remove it?
???
it randomly started
but its still the same
i fixed it
but now something is wrong with ah 0x42 int 0x13 in the load_root function
see that it's in a different position
and already taken care of by BPB_FATSz16
db 0x10 ;size of packet (16 bytes)
db 0 ;always 0
dw 32 ;number of sectors to read
dw 0x0000 ;offset
dw 0x0500 ;adress
dq 9 ;LBA``` ah 0x42 int 0x13 is not working and it has to be an issue with the DAP
but i dont know what
the root directory is 32 sectors big
the root sector starts at sector 9, so the LBA is correct, too
guys this is very strange
the maximum number of sectors that i can read is 22
if i set it higher, the program just stop working at this point
can you upload the code you currently have?
ideally to GitHub
i have error and error2
thats a debug feature, so i can switch between them and check, which part of the bootloader doesnt work
also
You are aware setting sp to 0x7E00 will overwrite the end of your boot sector?
what error code do you get?
nasm -f bin kernel.asm -o kernel.bin
dd if=/dev/zero of=disk.img bs=1M count=16
mkdosfs -F 16 disk.img
dd if=boot.bin of=disk.img bs=1 count=11 conv=notrunc
dd if=boot.bin of=disk.img bs=1 count=450 seek=62 skip=62 conv=notrunc
mcopy -i disk.img -D o kernel.bin ::/KERNEL.BIN
qemu-system-i386 -hda disk.img -m 2M``` i think something is wrong with the build script
because the search_kernel function doesnt find it
E5
thats the error code of the search_kernel function
i fixed it, because i changed in the dap 0x500 to 0x800
but i dont know why this works
and why 0x500 doesnt work
there has to be something wrong with the build script, because when i use other bootloaders, they dont find the kernel.bin file, too
maybe you could help me please? I am not very familiar with Linux commands
is kernel.bin in your fat image?
what do you mean?
what's going on here? a 16 bit real mode os? is it 1999 again?

dos school?
yeah, IBM PC DOS shool
no really whats a dos school
there you learn 8086 assembly
so it's an 8086 assembly course
a real school that only teaches 30 year outdated tech?
And you expect someone to attend?
yes, me
but what's the academic relevance, what job can you get knowing an antique architecture
i can work at IBM and code their PC DOS
are you trolling? I know you're trolling.
man, did you really thought this was real? im just joking
was gonna say, IBM ceased support for pc dos in 2000 lol
can't assume anything here, too many trolls and newbies
i am a newbie
if you're diving straight into assembly you aren't that much of a newbie
but im only learning it for 3 weeks
my first ever os was a 16 bit nasm based os
it literally was in 1999, I lost the source code
oh
me too
this is my first OS
only way is up
right now i am trying to implement FAT16 in my Bootloader but its not working
what's the os github again, I can't scroll up to the top on mobile
is it a multi stage bootloader?
https://github.com/Xiromos/xiromos this is the OS without FAT16, because FAT16 is currently not working
no
change to a multi stage loader and it's easier
you use the 512 byte boot sector to load some of the spare sectors before the fat starts that are usually empty
and you stash a stage 2 there
https://github.com/Joshua-Riek/x86-bootloader/blob/master/src/boot16.asm but this guys also made a bootloader into 512 bytes
stage 2 can then be much bigger
tying to put proper FS code into 512 bytes is a chore
but i want to try
good luck
thank you
what is your end goal with the os? make something like dos? or go further? add multi tasking? a gui?
my end goal is to implement my own text editor and my own assembler + own compiler with own programming language, so i can actually code in my own OS
but first i have to implement FAT16
which is already pretty complicated
no gui
multitasking would be nice
how will you protect programs from each other in real mode?
or is your end goal protected mode?
not really
first it will be singletasking
mac os classic memory model
yeah, i will
what do you mean?
please guys, is everything okay with the build script?
because other bootloaders doesnt work, too
i tried two other and both said, file not found
i tried the command: mdir -i disk.img ::
it showed the kernel.bin like this: KERNEL BIN
and i updated my bootloader, so now i calculate the root directory start and the sectors
but how do i put the RootStartSec value into the DAP?
because i cant just write it like this: dq [RootStartSec]
there are 3 spaces in between
so there are 12 chars??
exactly
but
in fat16
a filename must be 11 chars long
8 for the name and 3 for the extension
i know
so why
are you sure?
but when i look on the disk with this command: mdir -i disk.img ::, it shows kernel bin with 3 spaces
have you looked into the hexdump?
oh yeah dont worry then
just make sure your string is 11 chars long, mtools just add padding between the name and the extension
what matters is the on-disk representation
ahh
what does that mean?
open disk.img in a hex editor
the real name of your file on the disk
look, there is this random F8 FF FF FF FF FF
the filename looks fine
11 chars, that's fine
i changed the DAP to the calculated values, but it still doesnt find any kernel.bin file.
btw, is the adress random?
maybe the mcopy command doesnt copy kernel.bin into the root directory?
it does, unless if you decide to put it in another directory
i didnt put it anywhere
ig you copied the file in the rootdir
yes
they just gave a program ram and politely asked that it didnt take too much
basically offloading memory management to the user-end developers
;(BPB_RootEntry * 32) + (BytesPerSec - 1) / BytesPerSec
mov ax, [BPB_RootEntry]
mov bx, 32
mul bx
mov bx, [BPB_BytesPerSec]
add ax, bx
dec ax
xor dx, dx
div bx
mov [RootDirSectors], ax
mov [dap+2], ax
;calculate root dir start
;ReservedAreaCnt + (NumberOfFATs * FATSz16)
xor ax, ax
mov al, [BPB_NumberOfFATs]
mov bx, [BPB_FATSz16]
mul bx
add ax, [BPB_ReservedAreaCnt]
mov [RootStartSec], ax
mov [dap+8], ax
mov word [dap+10], 0
mov word [dap+12], 0
mov word [dap+14], 0
;data start sector
xor ax, ax
mov ax, [RootStartSec]
add ax, [RootDirSectors]
mov [DataStartSector], ax
;data sectors
;-----------
;lba extended mode
clc
mov ah, 0x41
mov bx, 0x55aa
mov dl, [BS_DriveNumber]
int 0x13
jc error
cmp bx, 0xaa55
je load_root
mov si, no_supp
mov bl, 0x0c
call print_start
jmp halt
load_root:
;BIOS extended disk read function
mov ah, 0x42
mov si, dap
mov dl, [BS_DriveNumber]
int 0x13
jc error
;detect ram
clc
int 0x12 ;ax = memory in KB
mov bl, 0x04
jc error
mov si, ram_ok
mov bl, 0x0a
call print_start
xor dx, dx
mov dx, word [BPB_RootEntry]
mov di, 0x0800
push di
search_kernel:
push cx
mov cx, 11 ;length of file name, needed for 'rep'
mov si, file_kernel_bin ;ds:si = name
push di
rep cmpsb
pop di
pop cx
je load_FAT
add di, 32
dec dx
jnz search_kernel
mov bl, 0x0c
jmp error```
db 0x10 ;size of packet (16 bytes)
db 0 ;always 0
dw 32 ;number of sectors to read
dw 0x0800 ;offset
dw 0x0000 ;adress
dq 0 ;LBA
GUYS
IT WORKED
I found kernel.bin!!!
but why?
i changed the adress with the offset in the dap
GG!
yes
but why?
does someone know?
am i doing something wrong?
why did it work? probably because its right i guess?
in the osdev wiki it said, first the offset and then the segment, but here i swapped it both
this should be wrong, but it worked
yes, like this
well where are u loading the kernel
in memory
no shit
the osdev wiki is correct
then it only worked by coincidence
this is correct
small endian
Windows sponsored Apple hater
0x2000
mov di, [es:di+0x1a] ;di = cluster no.
mov word [cluster], di
mov si, ok_msg
call print_start
mov ax, [BPB_FATSz16]
mov bx, [BPB_NumberOfFATs]
mul bx
mov [dap+0x02], ax
mov [dap+0x04], word 0x1300
mov [dap+0x06], word 0x0000
mov ax, [BPB_ReservedAreaCnt]
add ax, [BPB_HiddenSectors]
mov [dap+0x08], ax
mov dword [dap+10], 0
mov word [dap+14], 0
mov si, dap
call read_sectors
load_kernel:
mov word [dap+0x06], 0x2000
kernel_loop:
mov si, ok_msg
call print_start
mov ax, word [cluster]
call cluster_to_sec
mov [dap+0x08], ax
mov bx, [BPB_SectorsPerCluster]
mov [dap+0x02], bx
mov [dap+0x04], word 0x0000
mov [dap+10], dword 0
mov [dap+14], word 0
mov si, dap
call read_sectors
mov cl, [BPB_SectorsPerCluster]
mov ax, 512
mul cl
add [dap+0x04], ax
mov bx, [cluster]
shl bx, 1
mov ax, [bx+0x1300]
mov [cluster], ax
cmp ax, 0xFFF8
jb kernel_loop
loaded:
jmp 0x2000
in the load_FAT function: FATSz16 * NumberOfFATs = number of sectors to load, BPB_ReservedAreaCnt + HiddenSectors = first sector to load
and i am loading it to 0x1300
should work, right?
of course not, because the read_sectors function just stops
that points to an error in the DAP
osdev wiki says, if you want to read the disk with ah=0x42 and int 0x13 you have to set ds:si to the adress in memory
but i dont understand this point
ds is the offset? i set it to zero
but what is with si? it contains the whole DAP, not only the adress
is this correct?
ds is the segment
si is the offset
wait
now everything makes sense
THIS is why in my bootloader segment and offset are in the wrong place
ohh
okay perfect, everything works except the jump to the kernel
you're almost done 💪
yeah, lets go
thank you so much
mov si, ok_msg
call print_start
mov ax, word [cluster]
call cluster_to_sec ;get the first sector of the cluster
mov word [dap+0x08], ax ;ax = first sector of cluster in data area
;mov word [dap+10], 0
;mov dword [dap+12], 0
xor bx, bx
mov bl, [BPB_SectorsPerCluster]
mov [dap+0x02], bx ;number of sectors to read
mov word [dap+10], 0
mov dword [dap+12], 0
mov si, dap
call read_sectors ;load the cluster into memory
mov cl, [BPB_SectorsPerCluster]
mov ax, 512
mul cl
add [dap+0x04], ax
add word [dap+0x06], 0x1000 >> 4 ; = 0x100
mov bx, [cluster]
shl bx, 1 ;cluster * 2
mov ax, [0x1300+bx] ;[bx+0x1300]
mov [cluster], ax
cmp ax, 2
jb error
cmp ax, 0xFFF8 ;check if its the last cluster
jb kernel_loop ;if not, load the next cluster
loaded:
mov si, ok_msg
call print_start
jmp 0x2000:0x0000
hlt
alright guys, my bootloader had this bug that it could load only 2048 Bytes (4 sectors)
but then is asked chatgpt for help and he said i should add this line:
now it works perfect, but i want to understand what this line does
does someone know?
btw i uploaded my bootloader to github, you can see the full code there if you want
how do you get information from the bootloader (like BPB_SectorsPerCluster or DataStartSector) into the kernel?
The kernel can just read it?
yeah how?
The boot sector is still in memory, right?
yes
how do i get a value from 0x0C:0x7c00 ?
mov ax, [0x0c:0x7c00]
and then mov [sec_per_cluster], ax
Do you know how x86 segmentation works?
You can't do that directly. You first need to load a segment register with the appropriate segment.
that was a mistake, i first have to set ds to the segment (0x7c00) and then get the offset (0x0c) into ax
no
0x7C00 is the offset
0x0C is the segment here
;get values from the bootsector
xor ax, ax
mov ds, ax
mov al, [0x7c00+13]
mov [sec_per_cluster], al
mov ax, [0x7c00+17]
mov [root_entries], ax
mov al, [0x7c00+21]
mov [drive_number], al
mov ax, [0x7c00+59]
mov [data_start_sec], ax
mov ax, 0x3500
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x0FFFF
sti```
the bootloader is at 0x0000:0x7c00 i think
but if i try to load programs from the disk with same method as in the bootloader, it shows a disk error
i think there are wrong values
something is wrong with it
bruh chatgpt with real mode assembly
you should check all the values you copied from the bootsector
wouldnt segment 0x7C00 mean address 0x7C000 + offset 
if i load the kernel to 0x0000:0x3500, then the segment registers should be set to zero and the [org] to 0x3500
Correct
mov cx, 11
push di
repe cmpsb
pop di
je search_program_done
add di, 32
dec dx
jnz search_program_loop
jmp program_notfound
search_program_done:
mov di, [es:di+0x01a]
mov word [program_cluster], di
ret
load_program:
mov [program_dap+4], word 0x8500
mov [program_dap+6], word 0x0000
load_programs_loop:
mov ax, word [program_cluster] ;first cluster of the program
call cluster_to_sec ;get the first sector
mov [program_dap+8], ax ;set LBA
xor bx, bx
mov bl, [sec_per_cluster]
mov [program_dap+2], bx ;number of sectors to read
mov word [program_dap+10], 0 ;fill the rest of the LBA field with zeros
mov word [program_dap+12], 0
mov word [program_dap+14], 0
mov si, program_dap
call read_sectors
mov cl, [sec_per_cluster]
mov ax, 512 ;standard size of FAT16 cluster
mul cl
add [program_dap+4], ax ;add one cluster to the memory adress
adc word [program_dap+6], 0x100 ;increase buffer for next cluster
mov bx, [program_cluster] ;get the cluster-number
shl bx, 1 ;multiply it by 2, because [cluster] is 16-bit, but a FAT entry is 32bit
mov ax, [0x2000+bx] ;read the value for the next cluster number
mov [program_cluster], ax ;save the value for next cluster
cmp ax, 2
jb invalid_cluster
cmp ax, 0xFFF8 ;check if its the last cluster
jb load_programs_loop
jmp 0x0000:0x8500``` alright, and if i jump to a program at 0x0000:0x8500, the segment registers of the program have to be zero and the [org] 0x8500
i dont understand why this doesnt work in the kernel, but in the bootloader it works
its the same function
stosw
what do you mean?
i dont understand why its not working in the kernel. it basically the same function like in the bootloader, the only difference is, that here i load a program and not the kernel. First i tought, the segment registers are set wrong, but they are in the bootloader and in the kernel the same
If your having a hard time it may be easier to try out C and doing some 64 bit stuff?
No it’s not actually lol
I just implemented cursor blinking into my kernel in like 5 extra lines of code because I was bored
The code is way more understandable in C and easier to write
64 bit takes away a lot of the legacy stuff
Like there are no segmentation register etc to deal with
but im not talking about cursor blinking
And you can end up doing alot of more advanced stuff later on if you want
Same for loading a file off a hard drive using portIO
Structuring it in C is easier still
really?
Yes
but to let the cursor blink you have to write 5 lines of code and for disk read 70 lines
Sure?
A disk driver may be more complex
But my kernel dosnt even have a disk driver
Because I haven’t even needed to make one
I just tell the bootloader to do it for me
And load a tar archive
but how do you load programs then?
From the .tar file
It’s like a zip file but simpler to parse
The bootloader does the hard bit for me
And later I can make a disk driver when I need it
Maybe I could even make one for nvme SSDs and be fancy
I’m not sure if you can do that in 16bit mode
But yeah 64 bit is way easier
You can get started and have a terminal and printf to log things in 15 minutes if you get flanterm and nanoprintf
Then get started to learn making a PMM and some paging code maybe
Get interupts working and a keyboard running
hm
i dont think, too
yeah you cant really
this is how i read from a file off the "disk" which is just a file loaded into memory via the bootloader
it takes in the path, a pointer of where to put the result, and how much to read
just somthing to think about if you want a break from assemby and 16 bit stuff

wait, you load at the start of the OS all programs into memory?
the bootloader loads an initramfs for the kernel. that may have some programs on it
many linux distros do this before loading the reak disk
so they can do some more complex stuff before fully booting perhaps
you just reclaim the memory later
that function parses a file in memory that has files in it
mov [sec_per_cluster], al
mov ax, [0x7c00+17]
mov [root_entries], ax
mov al, [0x7c00+21]
mov [drive_number], al
mov ax, [0x7c00+59]
mov [data_start_sec], ax
``` what am i doing wrong?
isnt this a valid way to get the information from the bootsector?
mov [sec_per_cluster], al``` invalid segment override
Because you have to load the segment first into the segment register you are using
If that is the segment that you are using sure
You can spesify a segment there
so ds:0x7c00
There is also fs and gs which are general purpose segments you may like to use for this
If that’s the memory your trying to access that sounds about right
i dont think mov immediate works with degments
*segment registers
true
i usually just
xor ax, ax
mov es, ax
or mov ax, 0x07c0
yep
guys, do you think it is possible to design and emulate an 8-bit/16-bit CPU and write an operating system for it?
yes
it's possible
i will try it
I think you should maybe try getting some userspace and low-level programming experience first
e.g. try writing an NES emulator in C
or an IBM PC emulator
tho the latter is a bit harder
okay
but now it has one
i pushed everything to my github
terminal upgrade
it looks a lot like the x16-PrOS terminal 
my next goal is to complete the texteditor and then implement writing on the disk with FAT16, so i can store files
better version
now i will try implement a write command (write a .txt file on the disk)
btw guys, why are these commands sometimes called cat and touch?
cat means concatenate because it can be given many input files and it prints them all out combined eg concatenation
the touch command creates an empty file if it dosnt exit or it updates the last modified date timestamp on it
interesting
but why is the touch command called touch?
is it because you touch the disk?
Or you just touch the file
Because it dosnt just make files
it's similar to cat that it's purpose is to just update the access/modification timestamps of a file
but it has a behavior where if a file doesn't exist it will create it
and my OS has an interrupt for reading or creating a text file:
mov ah, 0x01 (read file), mov ah, 0x02 (create file) int 0x22
both expect the file name in SI
thats called a systemcall
idk its 1970
;write filename attribute
mov si, file_test_txt
mov cx, 11
push di
rep movsb ;copies [ds:si] to [es:di]
pop di
mov byte [es:di+0x0b], 0x20 ;archive
mov [es:di+0x1a], bx ;first cluster
``` very interesting
movsb works, but mov byte [es:di+0x0b], 0x20 crashes
i tested everything with a print_hex function
before movsb, es was 0, ds my kernel segment and di was pointed to the root directory
after movsb it was the same
so why does mov byte [es:di+0x0b], 0x20 doesnt work???
this is the line that crashes my whole systemcall
Im thinking about switching to unreal mode
look, here is my plan for my OS:
implement writing files to the disk
texteditor
implement own assembler
and then maybe unreal mode
i almost finished the texteditor and writing files to the disk, there are only some bugs to fix
im looking forward to program my own assembler
i think this is a lot of fun
why not protected mode
or even long mode
because i want to code in 16bit assembly
but why
unreal mode is an old hack
and some BIOS interrupts can even break the segments
if you want 4GB RAM, then just switch to protected mode
and to switch to unreal mode, you need to switch to protected mode first
- go back to real mode but without reloading the egments
you work more to get less
if you switch to unreal mode though it won’t WORK on 16-bit CPUs like the 8086 tho, as unreal mode REQUIRES a 32 bit cpu just to bump INTO pmode for the 4gb memory.
no real gain unless you want to cripple yourself to 16-bit code that can only run on 32-bit cpus
in which case either just go 32 bit or stay in 16 bits yk
or if your gonna do 32bit. might aswell go up to 64

me when lock myself to 2000’s and up hw (yuck)
i like 16 bit because it run on 286 :)
and 32 bit work on 486 and Pentium
you can’t just pop cs?
if you can’t pop Cs
then I don’t think you can push it either
ykyk
i think you can push cs but you cant pop it
yes you cannot pop it
you cannot mov into it either
you need to perform a far jump to load cs
i made a better read command
now it prints 30 lines and then waits for a key press
and if you press 'q' you can quit directly to the terminal
that cost me 3 hours btw
weird
why?
btw my OS doesnt run on the 8086 because it uses EDD, A20 Gate and in the hwinfo program 32bit registers
time to switch to protected mode man
well
maybe
i made a texteditor
tbh, it is surprisingly hard to code a texteditor
it uses mode 0x13, because it is easier to draw the cursor in this mode and you can track the BIOS cursor better
I wish my friends were interested in programming like me. because working together is twice as much fun
do you have insert working yet
e.g. navigate to the middle of a line, insert text, delete text, delete lines and delete chars?
you can navigate with the arrow keys and if you press backspace while the cursor is at the right site, the cursor jumps to the previous lines
and yeah, you can print chars and delete them
right now i am working at scrolling
because if the cursor wents to the last line, there are some visual bugs
guys lets goo!!
i almost implemented writing files ot the disk
there are some bugs
like for example the write-command overwrite something of the kernel, because when i restart the OS the bootloader gives an error when loading kernel.bin
but i am almost there
then i finally can save files from the texteditor to the disk
you could always just use a variable in memory to track the cursor position and use in/out to update it in text mode
are your commands built-in or actual loading programs?
true
is it loading programs from disk?
that is what i am doing
but i have to draw the cursor to this coordinates, while writing to the video memory. this is easier in textmode or graphics mode 0x13
the commands are build in, but the texteditor and some other stuff are actual programs
the file operation commands use systemcalls, for example ah=0x02 0x22 reads a txt file fron the disk
or ah=0x03 int 0x22 writes an empty txt file to the disk
yes
cool!
thank you
what do you want this os to be btw
do you have like a clear goal or are you just doing whatever you feel like doing?
my end goal is to have my own assembler built in so you can code in my OS. i think after this i will try another project, maybe a 32bit or 64 bit OS
because 16bit is quite limited
porting an assembler is pretty easy with file ops, are you sure you want to make your own?
yes, i want to try it
lets goo
better version
wait is the kernel still in assembly only?
yup
wow
thank you very much!
impressive.
new command
its kinda crazy how your making all these in assembly lol
what is hello.txt doing at 21592 clusters 
sealos flashbacks
why did bro cd into a .txt file 💀
btw 1819043176 is hell
haha, yeah thats a little bug
assembly isnt that hard if you get used to it
i fixed the rename command. now it actually saves the new name on the disk and it doesnt show wrong cluster numbers anymore
new command
omg i fixed this stupid bug finally..
cool

