Click to See Complete Forum and Search --> : Writing to a floppy in Pascal...


fbelzile
July 3rd, 2007, 03:27 AM
I'm making a mini-os (on a floppy) where there will be a question asked from the user. The user will respond and the computer will then write the answer to the floppy.

This is all done in Pascal and it has to use crt. It will all use BIOS interrupts so I can't use the normal DOS way of creating a text file. The answer has to be written onto the floppy somehow... Even writing on the floppy byte by byte will work, I just don't know how.

S_M_A
July 3rd, 2007, 05:35 AM
Since you make the OS yourself you have of course to make the file system yourself as well. Cough, cough... oh my, those BIOS documentation binders had a lot of dust on them...

INT13 implements diskette interface. Unfortunately I do not have these docs in electronic form but here is some info:
Regs for Read/Write/Verify
DL = Drive number (0,1)
DH = Head number (0,1)
CH = Track number (1.2 M,720k,1.44M = 0-79, orthers = 0-39)
CL = Sector number(320/360=1-8/9, 1.2M=1-15, 720k=1-9, 1.44M=1-18)
AL = Number of sectors
ES:BX = Buffer address

Functions (AH=function)
0 - Reset
1 - Get status from last operation
2 - Read sectors
3 - Write sectors
4 - Verify sectors

fbelzile
July 4th, 2007, 07:40 AM
Thanks a lot, I appreciate the fact that you went and looked for it. (If you actually did). Even with what you gave me, I'm not sure what to do. I'm no OS programmer. I don't know a lot of assembly and I'm not trying to learn how to make an OS. I just want this simple operation done.

Could someone give me an example on how to use this information to: write the information (one digit) of variable "a" to say, the first track of the first sector with head 1 (second side).

So would:
DL = 0
DH = 1
CH = 0
CL = 0
AH = 3
This be right? How do you use it?

Note that I'm not making a filesystem. I just want to write some numbers on the floppy directly. I'm using someone else's boot sector which keeps the computer in real mode and loads an executable (using the FAT12 filesystem).

Thanks for the continued help! :)

S_M_A
July 4th, 2007, 08:11 AM
I actually did go for the binder, call it nostalgy but I just can't dispose of it... :)

You're almost there with register setup. You want AL to be 1 though to write 1 sector and ES:BX to point to a buffer address holding 512 bytes of data (you can't just write one character). When registers are properly setup you issue the instruction int 13h to execute the operation.

However, it seems that you execute on some sort of OS since you talk about FAT12. In that case you should not use this method since you would most likely destroy the file system. Is this OS DOS compatible? Maybe you should use int 21 instead?

By the way, I also googled on "bios interrupts" and got at least one good hit http://www.ctyme.com/intr/cat-003.htm

fbelzile
July 4th, 2007, 09:40 AM
Wow, very useful site for reference. Thanks!

The boot loader simply tells the BIOS that the floppy is bootable, it's not the OS, it loads the OS. In this case it had to set up a file system to read off the disk and find a file to load. Once it finds my executable, it simply gives it control. I don't know whether the file system stays "in memory" or something :S

Here are my registers (with the small knowledge of assembly I have) :

DX = 0100h
CX = 0000h
AX = 0301h



My questions:

----- Where should I put the buffer?

;; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;;
;; ³ Interrupt Vector Table ³ 0000 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ BIOS Data Area ³ 0040 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ PrtScr Status / Unused ³ 0050 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ Image Load Address ³ 0060 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ Available Memory ³ nnnn ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ 2KB Boot Stack ³ A000 - 512 - 2KB ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ Boot Sector ³ A000 - 512 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; A000 ;;


----- How in the world do you use assembly with pascal. Reminder, I'm new to these languages. I will mix this stuff with pascal simply because the rest of it is written in pascal. How do I implement my variables in pascal, to assembly?

----- I will need to write 4 bytes total (for "byte" variables). Since I only need to write four bytes, can the sector look like this (yes, I counted all the zeros) :

12340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

How can I tell the program to write 108 0's after my four numbers? Can I see some example code?

S_M_A
July 4th, 2007, 10:41 AM
What Pascal is it, good old 16-bit Turbo Pascal?

TP Inline asm example from http://www.husseinsspace.com/teaching/udw/1996/asmnotes/chapeig.htmprogram InlineDemo;

var
Equip : word;

begin
asm { assembler statements }
int 11h { get equipment list }
mov Equip,ax { save in variable Equip }
end;
Writeln ('The equipment word for this computer is : ', Equip);
end. (Search phrase: inline assembly "Turbo Pascal")

Regarding the zeroes. Declare a 512 bytes big array in Pascal and use it for buffer when writing/reading. If declared within the Pascal code it should be mapped to a safe location.

fbelzile
July 4th, 2007, 10:18 PM
Alright perfect. I think I got everything except one thing:

I've created an array and I got the sector (all 512 bytes of it) var'ed as "sector." :P
How do I "connect" this array to the buffer address that will be used to write to the sector on the floppy?

Thanks again! I'm almost done, getting closer and closer!

S_M_A
July 5th, 2007, 06:08 AM
I think the instruction les bx, buf will accomplish what you want. If it doesn't work I will try to locate some of my old stuff, pray that it's not on 5,25 inch floppy... :)

fbelzile
July 5th, 2007, 11:34 AM
Thanks for looking once again. I'm still not sure what "les bx, buf" will do...
Will it feed the buffer into bx? Would it be "les bx, sector" in my case?
What do I put into ES?

Here's something I just wrote


mov DX, 0100h
mov CX, 0000h
mov AL, ??h
mov ES, AL
mov AL, 0
mov AX, 0301h
mov ES:[BX], sector
int 13h


Don't laugh at my code :)
Where does the "les bx, sector" come in? Should I use that instead of the "mov ES:[BX], sector"

Sorry for bombarding you with questions... I'm like that :)
Thanks again!

S_M_A
July 5th, 2007, 11:46 AM
No problem, just as long as you know that my memory might be wrong... :)
AL should be 1, you just want to operate on 1 sector (512 bytes)

LES BX, sector should replace your mov ES:[BX], sector

What LES does is load a segment/offset register pair with the address of sector (I hope). Most likely DS is already properly set so you might also tryMOV AX, DS
MOV ES, AX
MOV BX, offset sectorI guess that the debugger is an invaluable tool now... :)

S_M_A
July 5th, 2007, 11:50 AM
Just saw, the lines from mov al, ?? - mov al, 0 should also be replaced

fbelzile
July 5th, 2007, 12:10 PM
Yep, kinda hard to debug in real mode... The only way to check is to read from the disk.
Here's my code now:

... Pascal Stuff ...

asm
mov DX, 0100h
mov CX, 0000h
mov AX, DS
mov ES, AX
mov AX, 0301h
mov BX, offset sector
int 13h

end;
end.

S_M_A
July 5th, 2007, 12:27 PM
Eh, can't you use the debugger? As I remember it was possible to run in real mode. Well as long as there is some way of testing. To bad I throwed away all 16-bit tools a couple of years ago.

I'm curious! What was the result?

fbelzile
July 5th, 2007, 02:34 PM
Well, after updating Turbo Pascal to version 6 (because 5.5 didn't like "asm")...

It worked! :)

Well, it seemed to work. The computer asked me what I wanted it to, I answered. Then I heard the floppy drive spin again and seemed like it wrote something on the disk.

I'm just making a program now to read the first sector of the first track of the second side to see if it actually did its job.

I'll let you know if it really worked!

Thanks for sticking with me and teaching me while doing this. It's hard to find information on the internet about this stuff. You were the only thing I had and I appreciate your help. I'd hug you if you were here ;)

EDIT:
How would you read the disk... From what you said, I have to change AH to equal 2. But what would the buffer thing look like? Can have the sector as a string so I can print it to the screen using writeln?

EDIT2: I just looked and you can't have a string longer than 255 characters. So this means I have to make another array. How do you "print" arrays?

S_M_A
July 5th, 2007, 03:03 PM
I'm glad I could help you.

Yes, to read you just need to change AH to 2 the rest of the code is unchanged. Read data from floppy goes to your variable sector. The data itself is just a bunch of bytes so if you want to print them you first have to format them as text (byte for byte -> ASCII)

Writeln by the way. I wonder what kind of system routines it is dependent of. If writeln use any of DOS int21 routines using writeln will not be good at all...

Try it however, a crash isn't a catastrophy I guess? If it does not work I guess I will have to get the binder again for int10 documentation (or was it 16?) :)

One more thing that struck me. You better check the TP 6 documentation for what registers that you have to preserve when doing inline assembly. Failing to save those needed will cause disaster.

fbelzile
July 5th, 2007, 03:28 PM
I've asked the same questions... As long as it works! hehe...

S_M_A, you deserve a cookie! Everything worked out PERFECT! :)
I just printed out the first four bytes of the new array, called rsector, because thats all I care about.

I have one other question, but I don't care if you know the answer... You've helped me too much :P

How do you give control to the hard drive after my program stopped. Please tell me "theres an interrupt for that!" Hopefully I don't need drivers... I'm running on a 6 year old laptop, so I doubt theres anything new.

S_M_A
July 5th, 2007, 03:34 PM
Give control to the hard drive? Now I don't understand...

There is a int21h AH=0 actually that's called when your program terminates but that will TP add for you (and again, this is a DOS int so without DOS...)

fbelzile
July 5th, 2007, 03:44 PM
All this is being ran in real mode on a floppy disk when the computer is booted. I just wanted to know if there was a way to boot to the hard drive after my program wrote that sector on the floppy.

Note that this was like a mini operating system, there is nothing to go back to after the program is done its instructions. I want it to boot to the hard drive, and load windows.

S_M_A
July 5th, 2007, 03:53 PM
Ah, that might be hard I guess. Since you have booted on floppy the BIOS boot order is obviously set to order floppy, HD, CD or something similar.

So, to reboot from harddrive you have to change BIOS settings first (or eject floppy). Let me check if I can find something useful on the reboot issue. Putting out a string saying "Eject floppy and press ENTER to reboot" could be a solution?

fbelzile
July 5th, 2007, 04:01 PM
I guess that would work, but I really don't want to have the user eject the floppy and put it back in during the windows boot screen.

The bytes on the floppy are there for a reason. They'll be read by a startup program in windows and then stuff will happen depending on the answers...
No this isn't a prank on anyone... Its for simply starting up various programs like Itunes and MSN.

So I don't want to have to do anything phyically to make it boot to the hard drive.

Sorry if I'm picky :p I learn at the same time. I don't like easy routes.

S_M_A
July 5th, 2007, 04:16 PM
Ok then you wouldn't want to change BIOS either.

All I can think of is to load bootstrap from HD just as BIOS do it and hope that the BIOS data area is unaffected by the execution of your TP application. That I haven't a clue about I have to admit... I guess the best way forward in this issue is to find some linux kernel source and try to understand what it does.

Edit: Some second thoughts... the memory location for the HD bootstrap is occupied with floppy bootstrap while your app is running. Hm, this might be even harder then I thought...

fbelzile
July 5th, 2007, 05:49 PM
Yes! Well, at least I found out it's possible... Theres something that does more than what I want. Its called Smart Boot Manager. There is code, done in assembly, but this stuff is way over my head:

http://sourceforge.krugle.com/kse/codespaces/Akrgr4

I'll look to see if there is a smaller version like this that only focuses on loading the hard drive.

S_M_A
July 5th, 2007, 06:04 PM
Cool! I thought that boot managers just could handle booting from HDs. If you find one that can select both FD and HDs I guess you could use that without really bother how they do it?

fbelzile
July 5th, 2007, 07:56 PM
We shouldn't have celebrated so soon... I just tried the floppy, by actually rebooting... It didn't work. I've only tested it out with Bochs... That's why I assumed it worked.

By actually booting to the floppy it said that the first four bytes were "0000." I guess that means it didn't write correctly, read correctly, or both.

What would be different between Bochs and a real computer? The BIOS? I've also tried the floppy on a fairly new computer and it didn't work.

Here is the full pascal code:


uses crt;

var
choice1 : byte;
choice2 : byte;
choice3 : byte;
choice4 : byte;
sector : array[1..512] of byte;
rsector : array[1..512] of byte;
i : Integer;

procedure final;
begin
sector[1] := choice1;
sector[2] := choice2;
sector[3] := choice3;
sector[4] := choice4;

for i := 5 to 512 do
sector[i] := 0;

asm
mov DX, 0100h
mov CX, 0000h
mov AX, DS
mov ES, AX
mov AX, 0301h
mov BX, offset sector
int 13h
end;

asm
mov DX, 0100h
mov CX, 0000h
mov AX, DS
mov ES, AX
mov AX, 0201h
mov BX, offset rsector
int 13h
end;


writeln (' ');
writeln ('This is the first four bytes of the sector:');
writeln (' ');
write (rsector[1]);
write (rsector[2]);
write (rsector[3]);
write (rsector[4]);

halt;
end;

begin
CLRSCR;
TextColor(10);
writeln (' _______________________________________________________ ');
writeln (' | |');
writeln (' | What programs would you like to start-up upon boot? |');
writeln (' | |');
writeln (' | 1. Itunes 2. Firefox |');
writeln (' | 3. MSN Messenger 4. Outlook Express |');
writeln (' | |');
writeln (' | Enter "0" to end your selections. No letters! |');
writeln (' |_______________________________________________________|');
writeln (' ');

repeat
write (':');
readln (choice1);
if choice1 = 0 then
begin
choice2 := 0;
choice3 := 0;
choice4 := 0;

final;

end;

if choice1 > 4 then
begin
writeln (' Number too high. Try again. ');
end;

until choice1 < 5;

repeat
write ('?');
readln (choice2);

if choice2 = 0 then
begin
choice3 := 0;
choice4 := 0;

final;

end;

if choice2 > 4 then
begin
writeln (' Number too high. Try again. ');
end;

until choice2 < 5;


repeat
write ('?');
readln (choice3);

if choice3 = 0 then
begin
choice4 := 0;

final;

end;

if choice3 > 4 then
begin
writeln (' Number too high. Try again. ');
end;

until choice3 < 5;


repeat
write ('?');
readln (choice4);

if choice4 > 4 then
begin
writeln (' Number too high. Try again. ');
end;

final;

until choice4 < 5;
end.


What about the "LES BX, sector" I'll try that now.
This also bugs me while I'm reading the sector: "MOV BX, offset rsector"
Shouldn't it be the other way around when reading?