Page 1 of 1
Making an OS user programmable
Posted: Fri Nov 17, 2006 1:34 am
by nitinjavakid
Having learnt a bit about VESA(thanks to Brendan), I would like to implement a small 2d library for my OS. Something similar to BGI in Turbo C(if you remember). But I have written all the functions in assembly(nasm) and would like to make them usable to other C programs written by users. I saw some for the tutorials but they just showed how kernel is made in C. For better understanding of the problem, let me put an example.
This is the exact procedure(Is it possible or I have declare rect function as subfunction of an interrupt)
function _rect is defined by the OS.
user creates a program
void main()
{
rect(..some args...);
}
compiles it and stores it as a .bin file onto the filesystem(provided by the OS). (Here, I donno from where _rect function will come be taken while linking)
OS reads the file and copies all the it into memory. Set the segment registers to where it has loaded the program and jumps to the first program instruction.
Is it possible without interrupts?
Posted: Fri Nov 17, 2006 3:08 am
by martin.zielinski
What you mean by storing the app as .bin? If you mean a flat binary file than you will need to implement some form of executable format. A plain binary file do not store import tables and such stuff. So you are restricted to static linking. This is in my opinion not the right way, because this will include the hardware-manipulation code directly in the user-app, which could be a serious security problem, because you have to run the app in os-privileg.
So basicly what you need is some form of binary executable format that contains import/export tables (PE, ELF, whatever) to allow you dynamic linkage. This add a lot of flexibility.
Here is a simple scratch how this could be done:
- Kernel contains basic functionality and the HAL
- HAL implements accessors to the hardware and defines an interface for
"userland-usable-libraries"
- GfxLib links dynamicly to the HAL and implements gfx-functionality based
on the interface the HAL provided
- MyCoolApp links staticly or dynamicly to the gfx-lib and uses its exported
functions to accomplish it's task
Posted: Fri Nov 17, 2006 5:06 am
by Combuster
You probably want to provide some sort of graphics library to the programmer. Its not hard to explain for gnu sytems, but as i have no clue how your toolchain works you have to figure that part.
Globally you have to do these steps
- Write the asm routines using the C Calling Convention
- Write C Headers with the prototypes of the functions you've just written
- Compile the graphics code
- Link/Archive the graphics code into an library (1)
- Compile the user program
- Link the user program with the archive created above
1: you can skip this step if you dont know how this works and you dont mind supplying all .o files manually to the linker in the last step. Also in this step you might be able to create shared libraries, DLL, .so's and that sort of thing.
Doing things the DOS way and include all graphics code in the end application can be a good place to start to avoid hassles (downside is that you will generate big binaries this way).
Sample ASM file
Corresponding C header
Posted: Fri Nov 17, 2006 5:23 am
by nitinjavakid
Thanks!
Looked at your source code. The header file is indirectly using interrupts to call kernel functions. Is that the same way in which windows it is 0x21 and on linux 0x80 call system calls? I mean
int main()
{
printf("Am I Calling an interrupt");
return 0;
}
Will the above function printf call 0x80 interrupt if it is compiled for linux?
Posted: Fri Nov 17, 2006 5:01 pm
by Combuster
I have no clue as to how the kernel calls in linux/windows work. The ASM file is just a small example simply calling the kernel. You could put actual code in there if you'd want it that way. (Some things dont need a kernel, and therefore no system call/interrupt)
Posted: Fri Nov 17, 2006 9:56 pm
by prajwal
Syscall (in case of x86) is done by means of call gates/int gates...
Whenever user program tries to access any kernel resource like kernel memory for DMA transfer (in disk read/write), process table, file system tables... syscalls are required as kernel will be running (usually) at ring 0 and user program in ring x > 0.... this is how u enforce security for OS / kernel.... When it comes to printf... ultimately the chars has to be displayed on screen which invovles screen buffer updation which is part of kernel mem... so, syscall (ints) isinvovled in printf also.....
I have heard many guys (freshers out of college) saying "one should use library calls especially for file access ie. fopen instead of open, so that it doesn;t invovle context switch... that is totally a wrong notion.. its true that it decreases the no. of context switches due to library level buffering but ultimatey the task is carried out by kernel for the user program....
Posted: Sat Nov 18, 2006 12:11 pm
by nitinjavakid
main.c
Code: Select all
#include "link.h"
void kmain()
{
unsigned char *vidmem = (unsigned char *)0xB8000;
vidmem[0] = 'r'; // before going into print
print();
vidmem[0] = 's'; //after coming out from print
for(;;);
}
link.asm
Code: Select all
section .text
[bits 32]
global _print
_print:
push eax
push ds
mov ax,0x08
mov ds,ax
mov eax, 0xB8000
mov byte [eax],'A'
pop ds
pop eax
jmp $ ; for checking
ret
link.h
command prompt commands
Code: Select all
nasm -f bin bootsect.asm -o bootsect.bin
nasm -f elf link.asm -o link.o
gcc -ffreestanding -mno-stack-arg-probe -c main.c -o main.o
ld -e _kmain -Ttext 0x1000 -o kernel.o main.o link.o
ld -i -e _kmain -Ttext 0x1000 -o kernel.o main.o link.o
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin
makeboot a.img bootsect.bin kernel.bin
I am getting 's' on the top left of the screen which should not be the case if print is called. So, I assume that print is not being called. What could be the mistake?
objdump for more info
Code: Select all
E:\osdev>objdump -d -f kernel.o
kernel.o: file format pe-i386
architecture: i386, flags 0x0000013b:
HAS_RELOC, EXEC_P, HAS_DEBUG, HAS_SYMS, HAS_LOCALS, D_PAGED
start address 0x00001000
Disassembly of section .text:
00001000 <_kmain>:
1000: 55 push %ebp
1001: 89 e5 mov %esp,%ebp
1003: 83 ec 08 sub $0x8,%esp
1006: c7 45 fc 00 80 0b 00 movl $0xb8000,0xfffffffc(%ebp)
100d: 8b 45 fc mov 0xfffffffc(%ebp),%eax
1010: c6 00 72 movb $0x72,(%eax)
1013: e8 00 00 00 00 call 1018 <_kmain+0x18>
1018: 8b 45 fc mov 0xfffffffc(%ebp),%eax
101b: c6 00 73 movb $0x73,(%eax)
101e: eb fe jmp 101e <_kmain+0x1e>
00001020 <_print>:
1020: 50 push %eax
1021: 1e push %ds
1022: 66 b8 08 00 mov $0x8,%ax
1026: 8e d8 movl %eax,%ds
1028: b8 00 80 0b 00 mov $0xb8000,%eax
102d: c6 00 41 movb $0x41,(%eax)
1030: 1f pop %ds
1031: 58 pop %eax
1032: eb fe jmp 1032 <_print+0x12>
1034: c3 ret
...
Posted: Sat Nov 18, 2006 1:51 pm
by nitinjavakid
From the output of objdump, all i can see is while calling kprint, jmp to next instruction is being performed
.
Posted: Sat Nov 18, 2006 1:56 pm
by Candy
nitinjavakid wrote:
Code: Select all
nasm -f bin bootsect.asm -o bootsect.bin
nasm -f elf link.asm -o link.o
gcc -ffreestanding -mno-stack-arg-probe -c main.c -o main.o
ld -e _kmain -Ttext 0x1000 -o kernel.o main.o link.o
ld -i -e _kmain -Ttext 0x1000 -o kernel.o main.o link.o
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin
makeboot a.img bootsect.bin kernel.bin
You link to the output file. Then you relink to the output file as a relocatable file (which seems pointless). You then pretend to have a non-relocatable output file (objdump doesn't relocate, ld should've done that but you overwrote the output with one that wasn't relocated) and objcopy just copies the current contents of the sections. That explains the call 0.
Remove the ld -i line and you should be all set. LD should relocate, objcopy creates the binary file. FYI, ld also has a --oformat flag that allows the same thing basically but is less error-prone (since LD will just warn you about intermediate linking to a binary file).
Posted: Sat Nov 18, 2006 2:05 pm
by nitinjavakid
on removing -i, program works fine but size of .bin file increases to a large extent(from 48 to 4118 approx. bytes). Is there any way to reduce that. Also, objdump shows the required code with some extra unwanted code(donno what that is for).
Posted: Sat Nov 18, 2006 2:30 pm
by nitinjavakid
ok got it now. Linker script can be used for such purposes.