Hi,
Ive started trying to code simple OS under FreePascalCompiler. If anyone is interested in it, or in OSDEV in Pascal then please read this:
If you want to skip RTL ommit the linking stage using the "-a" switch. FPC requires some external symbols, like:
FPC_INITIALIZEUNITS ; this function should initialize all the units
FPC_DO_EXIT ; what to do if the program ends
INIT$$SYSTEM ; init for basic system routines
It can looks like:
;--
global FPC_INITIALIZEUNITS
global FPC_DO_EXIT
global INIT$$SYSTEM
extern program_init
INIT$$SYSTEM:
start:
call program_init
ret
FPC_INITIALIZEUNITS:
ret
FPC_DO_EXIT:
ret
; --
compile this file, for example "nasm filename.asm -f aout"
all you have to do later is to link main pascal program and this tiny asm loader.
To output "flat binary":
ld asmout.o pascalprog.o --oformat binary -Ttext 0xtextsectionstart
If you`ll use some procedures/functions in the linking stage some errors will be displayed.. these are functions which FPC requires for property working, like copying parameters to a function. Look at FPC sources (it might be "rtl sources\inc\i386.inc"), if you dont find this procedure out there try to find it somewhere else in the sources tree.
Another useful thing is old, good intel syntax. To enable it use "-Rintel" switch in ppc386 command-line. You can then use assembler syntax like:
mov eax, $0DEADBEEF
mov esi, $012345
mov [esi], eax
...
This things are really basic. Its quite weird, but not difficult. When I`ll have some more free time I`ll try to describe this things much more clearier, and deeper.
If you have any questions, or you have write some your own piece of code, please write me: [email protected]
I hope this small text could help someone in Pascal-OSDEV.
Greetings, Crg.
OSDev in Pascal..
RE:OSDev in Pascal..
Ah, and a small example:
Remember to switch under pmode before that..
BTW: Every `uses' unit has initialization code, called INIT$$UNIT_NAME. <- this is a main procedure after Implementation and Interface stuff.
{
begin
code..
end.
}
!!!!!!!!!!!!!!!!!! i386.inc !!!!!!!!!!!!
{
THIS CODE IS GRABBED FROM THE FREEPASCALCOMPILER SOURCES
rtl_sources_dir\inc\i386.inc
}
{$asmmode ATT}
{$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
begin
asm
pushl %eax
pushl %ecx
cld
movl dstr,%edi
movl sstr,%esi
xorl %eax,%eax
movl len,%ecx
lodsb
cmpl %ecx,%eax
jbe .LStrCopy1
movl %ecx,%eax
.LStrCopy1:
stosb
cmpl $7,%eax
jl .LStrCopy2
movl %edi,%ecx { Align on 32bits }
negl %ecx
andl $3,%ecx
subl %ecx,%eax
rep
movsb
movl %eax,%ecx
andl $3,%eax
shrl $2,%ecx
rep
movsl
.LStrCopy2:
movl %eax,%ecx
rep
movsb
popl %ecx
popl %eax
end ['ESI','EDI'];
end;
!!!!!!!!!!!!!!!!!! i386.inc END !!!!!!!!!!!!
!!!!!!!!!!!!!!!!!! kernel.pas !!!!!!!!!!!!!!
{$I i386.inc}
var
screen : array [0..4000] of byte absolute $b8000;
i, j : word;
screen_x, screen_y : word;
procedure write_char(c:char); forward;
procedure puts(text: string); forward;
procedure puts(text: string);
var
i : word;
begin
i:= 1;
while 1 > 0 do begin
if (text[i] = #0) then break;
write_char(text[i]);
i:=i + 1;
end;
end;
procedure write_char(c : char);
var
addr : ^char;
begin
if ((screen_x > 79) or (c = #10)) then begin
screen_x:= 0;
screen_y:= screen_y + 1;
end;
addr:= $0b8000;
addr:= addr + screen_x * 2 + screen_y * 160;
addr[0]:= c;
addr[1]:= #7;
screen_x := screen_x + 1;
end;
begin
screen_x:= 0;
screen_y:= 0;
puts('This is simple kernel..');
end.
!!!!!!!!!!!!!!!!!! kernel.pas END !!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!! loader.asm !!!!!!!!!!!!!!
global FPC_INITIALIZEUNITS
global FPC_DO_EXIT
global INIT$$SYSTEM
extern program_init
INIT$$SYSTEM:
start:
call program_init
ret
FPC_INITIALIZEUNITS:
ret
FPC_DO_EXIT:
ret
!!!!!!!!!!!!!!!!!! loader.asm END !!!!!!!!!!!!!!
to compile this type:
ppc386 kernel.pas -Cn -a -Rintel
nasm loader.asm -f aout -o loader.o
ld loader.o kernel.o --oformat binary -o kernel.img -Ttext 0xTEXTBASE
I hope I havent forgot about anything..
Remember to switch under pmode before that..
BTW: Every `uses' unit has initialization code, called INIT$$UNIT_NAME. <- this is a main procedure after Implementation and Interface stuff.
{
begin
code..
end.
}
!!!!!!!!!!!!!!!!!! i386.inc !!!!!!!!!!!!
{
THIS CODE IS GRABBED FROM THE FREEPASCALCOMPILER SOURCES
rtl_sources_dir\inc\i386.inc
}
{$asmmode ATT}
{$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
begin
asm
pushl %eax
pushl %ecx
cld
movl dstr,%edi
movl sstr,%esi
xorl %eax,%eax
movl len,%ecx
lodsb
cmpl %ecx,%eax
jbe .LStrCopy1
movl %ecx,%eax
.LStrCopy1:
stosb
cmpl $7,%eax
jl .LStrCopy2
movl %edi,%ecx { Align on 32bits }
negl %ecx
andl $3,%ecx
subl %ecx,%eax
rep
movsb
movl %eax,%ecx
andl $3,%eax
shrl $2,%ecx
rep
movsl
.LStrCopy2:
movl %eax,%ecx
rep
movsb
popl %ecx
popl %eax
end ['ESI','EDI'];
end;
!!!!!!!!!!!!!!!!!! i386.inc END !!!!!!!!!!!!
!!!!!!!!!!!!!!!!!! kernel.pas !!!!!!!!!!!!!!
{$I i386.inc}
var
screen : array [0..4000] of byte absolute $b8000;
i, j : word;
screen_x, screen_y : word;
procedure write_char(c:char); forward;
procedure puts(text: string); forward;
procedure puts(text: string);
var
i : word;
begin
i:= 1;
while 1 > 0 do begin
if (text[i] = #0) then break;
write_char(text[i]);
i:=i + 1;
end;
end;
procedure write_char(c : char);
var
addr : ^char;
begin
if ((screen_x > 79) or (c = #10)) then begin
screen_x:= 0;
screen_y:= screen_y + 1;
end;
addr:= $0b8000;
addr:= addr + screen_x * 2 + screen_y * 160;
addr[0]:= c;
addr[1]:= #7;
screen_x := screen_x + 1;
end;
begin
screen_x:= 0;
screen_y:= 0;
puts('This is simple kernel..');
end.
!!!!!!!!!!!!!!!!!! kernel.pas END !!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!! loader.asm !!!!!!!!!!!!!!
global FPC_INITIALIZEUNITS
global FPC_DO_EXIT
global INIT$$SYSTEM
extern program_init
INIT$$SYSTEM:
start:
call program_init
ret
FPC_INITIALIZEUNITS:
ret
FPC_DO_EXIT:
ret
!!!!!!!!!!!!!!!!!! loader.asm END !!!!!!!!!!!!!!
to compile this type:
ppc386 kernel.pas -Cn -a -Rintel
nasm loader.asm -f aout -o loader.o
ld loader.o kernel.o --oformat binary -o kernel.img -Ttext 0xTEXTBASE
I hope I havent forgot about anything..
Code: Select all
os.pas(45,12) Error: Incompatible types: got "LongInt" expected "^Char"
os.pas(62) Fatal: There were 1 errors compiling module, stopping
os.pas(62) Fatal: Compilation aborted
Why??
addr := PChar($0b8000) should work. ($0b8000 is an integer; you need to type-cast it to a pointer.)kazio0 wrote:addr:= $0b8000;Code: Select all
os.pas(45,12) Error: Incompatible types: got "LongInt" expected "^Char" os.pas(62) Fatal: There were 1 errors compiling module, stopping os.pas(62) Fatal: Compilation aborted
Why??