Thread: Need a new compiler/linker

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    150

    Need a new compiler/linker

    I need a compiler / linker that will put out 16-bit binary images to produce an operating system that i am writing. I was using djgpp, but from what i understand it's binaries will only operate properly in 32-bit protected mode. I need something that can produce real-mode binaries. Can anyone tell me how to produce these with djgpp or any other tools?
    HA! I WIN!

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by xixpsychoxix View Post
    I need a compiler / linker that will put out 16-bit binary images to produce an operating system that i am writing. I was using djgpp, but from what i understand it's binaries will only operate properly in 32-bit protected mode. I need something that can produce real-mode binaries. Can anyone tell me how to produce these with djgpp or any other tools?
    The Linux kernel uses a trick to compile real mode code using gcc. gcc always generates 32-bit code, but using an assembler directive, you can command the assembler to assume 16-bit mode, and produce the proper instruction prefixes for execution in real mode.

    To do this, add the following at the very top of any .c file you wish to use in real mode (outside of any function, and in fact, before you even include any header files, just to be safe):

    Code:
    __asm(".code16");
    Once the object file has been compiled and linked to produce an ELF image, you can flatten it to a raw binary format using:

    Code:
    objcopy -O binary input.elf output.bin
    This is used and accepted in the Linux kernel, so you might at least consider it. The only drawback in my opinion is code size. The 32-bit instructions plus 32-bit prefix will be significantly larger than the equivalent 16-bit code. So this probably isn't suitable for writing a boot sector, but you're probably hand-coding your boot sector in assembly language anyway.

    If you want true-blue 16 bit code, you'll need some other compiler. Borland Turbo C++ is freely available and is a very good 16-bit compiler.

    EDIT: I forgot to mention that everything I said is done on a Linux system. If you're using Windows, you can probably accomplish the same thing using the MinGW tool set.
    Last edited by brewbuck; 05-12-2009 at 09:46 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    An option would be Bruce's C compiler. It was used in Xen to produce the BIOS code for fully virtualized machines.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    The assembler is now generating the 16-bit code that I want and a test program ran successfully, but this program will not:

    Code:
    C source (called kernel.c):
    
    __asm (".code16");
    
    extern void print_a (char *);
    
    int main ()
    {
     print_a ("Hello, world!");
    
     test:
    
    	goto test;
    }
    followed by:

    Code:
    ASM source (called library.asm; assembled with NASM):
    
    [BITS 16]
    
    GLOBAL _print_a
    
    SECTION .text
    
    _print_a:
    
    	PUSH BP
    	MOV BP,SP
    	
    	MOV SI,[BP+8]
    	MOV AH,0x0E
    	MOV BX,0x0007
    
    .print_loop:
    
    	LODSB
    	OR AL,AL
    	JZ .done
    	INT 0x10
    	JMP .print_loop
    
    .done:
    
    	POP BP
    	RET
    My bootloader loads this code into memory at 0050:0000 and then executes a far return to said location. I am compiling under DJGPP using the following compiler/linker options:

    Code:
    gcc -ffreestanding -c kernel.c -o kernel.o
    ld -Ttext 0x50 -e _main --oformat binary kernel.o library.o -o kernel.bin
    Can anyone tell me why this code will not produce the line as i've written it? Whenever I change the code to print a character instead of a line, it works fine!!!
    HA! I WIN!

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you want to actually produce 16-bit code from C, then you need a proper 16-bit compiler. The bcc product I suggested is still a valid option, as is Turbo C. The former runs on Linux, the latter does not.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    Would you happen to be able to point me to a copy of Turbo C++? I searched it on google but i can't seem to find the latest version. My search only turned up Turbo C 2.something. Oh, and would the compiler / linker options be the same?
    HA! I WIN!

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, and no. The compiler options are similar for the most common options, but not by any means the same, and the linker I don't think have ANY similar option.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by xixpsychoxix View Post
    Can anyone tell me why this code will not produce the line as i've written it? Whenever I change the code to print a character instead of a line, it works fine!!!
    Dumb question maybe, but have you made sure that all the segment registers are set up correctly?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by matsp View Post
    No, and no. The compiler options are similar for the most common options, but not by any means the same, and the linker I don't think have ANY similar option.

    --
    Mats
    To produce a flat binary from Turbo C, compile using the tiny memory model and use exe2bin to convert the .exe to a .com file. Keep in mind that .com files have an implicit origin of 0x100.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    You know, i didnt check to see if the segment registers are set up right. I suppose I should've done that though. Are we guessing that is the problem then? I'll try that.
    HA! I WIN!

  11. #11
    Registered User
    Join Date
    Jul 2009
    Posts
    1
    As the code is 16 bit should be:
    Code:
    _print_a:
    
    	PUSH BP
    	MOV BP,SP
    	
    	MOV SI,[BP+4]  ; on the stack is BP and return address so it gives 4 bytes.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. compiler/linker flags in VS2008
    By Abda92 in forum C Programming
    Replies: 5
    Last Post: 04-04-2008, 01:28 PM
  2. Replies: 4
    Last Post: 09-02-2007, 08:47 PM
  3. A Simple Compiler/Linker
    By SMurf in forum C Programming
    Replies: 9
    Last Post: 02-17-2005, 03:53 PM
  4. minimalist compiler/linker
    By major_small in forum C++ Programming
    Replies: 8
    Last Post: 06-18-2004, 11:26 AM
  5. compiler/linker output
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 10-18-2001, 09:11 PM