Running .com files / API implementation
Running .com files / API implementation
Hello all.
I'm working on a 16 real mode os with FAT12 filesystem and now I need to make my OS execute (and return from) .com files. At the moment I can read the .com file from floppy and copy it to memory, but I don't know exactly how to run it (which registers I should change, pass the execution and return to the OS when the execution is done). Which steps should I take? (event the simplest method is welcome)
Thanks in advance,
Fergo
I'm working on a 16 real mode os with FAT12 filesystem and now I need to make my OS execute (and return from) .com files. At the moment I can read the .com file from floppy and copy it to memory, but I don't know exactly how to run it (which registers I should change, pass the execution and return to the OS when the execution is done). Which steps should I take? (event the simplest method is welcome)
Thanks in advance,
Fergo
Last edited by Fergo on Wed Feb 13, 2008 11:51 am, edited 1 time in total.
I would think that you just have to jump to the application in memory at offset 0x100 (if this is a standard DOS .com file). And also, standard .com files call int 13h, ah=0 to terminate execution, so you have make an interrupt handler for that too.
See
http://en.wikipedia.org/wiki/COM_file
and
http://www.uv.tietgen.dk/Staff/Mlha/PC/ ... /index.htm
Some .com files will expect these DOS services to be available
See
http://en.wikipedia.org/wiki/COM_file
and
http://www.uv.tietgen.dk/Staff/Mlha/PC/ ... /index.htm
Some .com files will expect these DOS services to be available
"Sufficiently advanced stupidity is indistinguishable from malice."
int 13h is the disk interrupt, ah=0 means 'reset disk system'. DOS .com files may do a simple ret (or retf, can't remember), int 20h (DOS 1.x termination, but still works in later versions), int 21h, ah=0 (same) or the recommended (DOS 2.0+) int 21h, ah=4ch.karekare0 wrote:And also, standard .com files call int 13h, ah=0 to terminate execution, so you have make an interrupt handler for that too.
JAL
I wrote a very simple dos clone (2k in size), that has well commented fasm code, that can load a com or mz exe, it also run some old dos games, so reading the source code may help.
See here:
http://board.flatassembler.net/topic.php?t=5275&start=0
See here:
http://board.flatassembler.net/topic.php?t=5275&start=0
Thanks again! I've tried and it worked pretty good.
I have another problem, so instead of creating a new topic I'm gonna ask here.
I've seen MikeOS source and it has a rustic API implementation. It's basically a lof of functions calls at the start of the kernel, and the address of this functions do not change, so third party programs can call them by a simples "call addr".
I'm writing my kernel in C, but I can't figure out how to do something similar. I have my functions (like Putch(), Getch(), etc.) in C using inline asm (using TC++ 3.0), and some of this functions have arguments (like the Putch, where the argument is the character to print):
I don't know exactly how to handle the arguments during the API call (which call the function at the kernel start and then, the real function is called). In asm is simple, because there isn't "arguments" in "functions". The value is passed directly to the registers by "mov" or by "push", and the API call it is really just a "call addr". I want to keep it close to C syntax, so when the user is creating an application to my OS and wants to print a character on screen, he just do "Putch('f');"
I'm sorry if I wasn't clear, and english is not my first language =/
Thanks in advance,
Fergo
I have another problem, so instead of creating a new topic I'm gonna ask here.
I've seen MikeOS source and it has a rustic API implementation. It's basically a lof of functions calls at the start of the kernel, and the address of this functions do not change, so third party programs can call them by a simples "call addr".
I'm writing my kernel in C, but I can't figure out how to do something similar. I have my functions (like Putch(), Getch(), etc.) in C using inline asm (using TC++ 3.0), and some of this functions have arguments (like the Putch, where the argument is the character to print):
Code: Select all
void putch(unsigned char c) {
asm mov ah, 0x0E
asm mov al, c
asm int 0x10
}
I'm sorry if I wasn't clear, and english is not my first language =/
Thanks in advance,
Fergo
You should look into how stack frames are organized in C, and how you could manipulate them to get the desired result. It is possible, but not trivial. Also, if you just use the function name in C, the linker is going to link it to that function. This means you need a stub function that calls the single kernel API dispatch function, which in turn calls the real function.Fergo wrote:I don't know exactly how to handle the arguments during the API call (which call the function at the kernel start and then, the real function is called).
JAL
Dex, I was analyzing your code from MiniDos again and then I realized that I did not understand what I thought I did. I'm confused in the part where you load the .com file to memory and passes execution to it.
I'm sorry to bother you, but can you explain with more details how the .com file is loaded and executed in MiniDOS and which registers should I change so the executable can run and return properly?
I've created my own code to run the "bounce.com" file included in MiniDos. The application runs, but crash the system when it finishes. That's why I opened MiniDos code to read again.
Thanks in advance,
Fergo
I'm sorry to bother you, but can you explain with more details how the .com file is loaded and executed in MiniDOS and which registers should I change so the executable can run and return properly?
I've created my own code to run the "bounce.com" file included in MiniDos. The application runs, but crash the system when it finishes. That's why I opened MiniDos code to read again.
Thanks in advance,
Fergo
Sorry for the double post, but here is the code of my Kernel, which is loaded at 0AC0:0000 and the bounce.com resides at 0AC0
As I said, bounce.com is loaded and executed, but crashes the system when I press "ESC" to end the application. Tetris and Invaders dont work.
Thanks again,
Fergo
Code: Select all
BITS 16
mov bx, 0x0AC0
mov ds, bx
mov bx, 0x0AC0
mov es, bx
;video mode to 80x25
mov ah, 0x00
mov al, 0x03
int 0x10
;write 'F' just for test
mov al, 'F'
mov ah, 0x0E
int 0x10
;wait for keypress
mov ah, 0x00
int 0x16
;save some regs, call to the .com address, and restore the regs
push ss
push sp
pusha
call 0x0AC0:0x0100
popa
pop sp
pop ss
;write 'E' for test
mov al, 'E'
mov ah, 0x0E
int 0x10
;wait for or keypress
mov ah, 0x00
int 0x16
TIMES 256-($-$$) DB 0
incbin "tetris.com"
Thanks again,
Fergo
Hi, first of all you need to code the int 21h functions and hook them up before invader or tetris will work.
Now to run a com file (that does not use any dos int's)
It needs something like this:
COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h
In the above case the com file would be loaded to 60h.
But do you really need a true com file format ?.
For your own OS is much simpler to have your own file format and use a simple "ret" , let me know if you just want a loadable file (eg: simple bin file) or you do want a true com file loader and i will try and help you.
Now to run a com file (that does not use any dos int's)
It needs something like this:
COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h
In the above case the com file would be loaded to 60h.
But do you really need a true com file format ?.
For your own OS is much simpler to have your own file format and use a simple "ret" , let me know if you just want a loadable file (eg: simple bin file) or you do want a true com file loader and i will try and help you.
Thanks for the information Dex.
About the file format: actually the only thing I want is to load applications, don't matter in which format, so I don't need to put everything into the same binary of my kernel.
I chose .com files because I thought they were the most simple ones, and as they are pretty common, I could load "third party" applications in my OS (like you did with Tetris/Invaders in MiniDos) without any troubles (I guess I was wrong...)
I didn't knew about the int 21 thing. I was supposing that the interruptions would be there, intact, and ready for use as long as I don't "overwrite" them.
As running .com files are not like I imagined, right now the only thing I want is some guidelines on how to setup the stack/regs to run some binary file (plain, .com, whatever) and return to my OS without any problem. I accept any suggestions, of course
Thanks a lot Dex! I'm sorry for taking you time with this questions.
Regards,
Fergo
About the file format: actually the only thing I want is to load applications, don't matter in which format, so I don't need to put everything into the same binary of my kernel.
I chose .com files because I thought they were the most simple ones, and as they are pretty common, I could load "third party" applications in my OS (like you did with Tetris/Invaders in MiniDos) without any troubles (I guess I was wrong...)
I didn't knew about the int 21 thing. I was supposing that the interruptions would be there, intact, and ready for use as long as I don't "overwrite" them.
As running .com files are not like I imagined, right now the only thing I want is some guidelines on how to setup the stack/regs to run some binary file (plain, .com, whatever) and return to my OS without any problem. I accept any suggestions, of course
Thanks a lot Dex! I'm sorry for taking you time with this questions.
Regards,
Fergo
- zaleschiemilgabriel
- Member
- Posts: 232
- Joined: Mon Feb 04, 2008 3:58 am
If you're writing your OS from scratch, there's no BIOS function that will do that for you, and BIOS is all you have to start with. If you want to load and execute specific file formats, you'll have to find a file format description and use BIOS int 13h to load the file from disk, then execute it:
* If you want to run DOS programs, you have to write support for all the int 21h functions, as DeX said. If you do this, then your question becomes invalid, because there's an int 21h that loads and executes programs and you will have already implemented that too.
* If you just want to run .com programs that don't use or rely on int 21h (or any other interrupts available in DOS), I think it's enough to load the .com file into memory and then jump at the location where you loaded it... This is just an idea. There are many ways to execute programs. It all depends on the format you want to use and what kind of support you are prepared to implement for it.
* If you want to run DOS programs, you have to write support for all the int 21h functions, as DeX said. If you do this, then your question becomes invalid, because there's an int 21h that loads and executes programs and you will have already implemented that too.
* If you just want to run .com programs that don't use or rely on int 21h (or any other interrupts available in DOS), I think it's enough to load the .com file into memory and then jump at the location where you loaded it... This is just an idea. There are many ways to execute programs. It all depends on the format you want to use and what kind of support you are prepared to implement for it.
Of course it's not that black&white. You could also implement the most used int 21h calls, and not others. You could decide which programs to run in your OS, check which calls they make, and implement only those.zaleschiemilgabriel wrote:* If you want to run DOS programs, you have to write support for all the int 21h functions
JAL