1

I'm following the guide to create a bootloader that draws rectangles on this webpage: https://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part

First, I need to create test.c and copy the following source code:

/* generate 16 bit code                                                 */
__asm__(".code16\n");
/* jump to main function or program code                                */
__asm__("jmpl $0x0000, $main\n");

#define MAX_COLS     320 /* maximum columns of the screen               */
#define MAX_ROWS     200 /* maximum rows of the screen                  */

/* function to print string onto the screen                             */
/* input ah = 0x0e                                                      */
/* input al = <character to print>                                      */
/* interrupt: 0x10                                                      */
/* we use interrupt 0x10 with function code 0x0e to print               */
/* a byte in al onto the screen                                         */
/* this function takes string as an argument and then                   */
/* prints character by character until it founds null                   */
/* character                                                            */
void printString(const char* pStr) {
     while(*pStr) {
          __asm__ __volatile__ (
               "int $0x10" : : "a"(0x0e00 | *pStr), "b"(0x0007)
          );
          ++pStr;
     }
}

/* function to get a keystroke from the keyboard                        */
/* input ah = 0x00                                                      */
/* input al = 0x00                                                      */
/* interrupt: 0x10                                                      */
/* we use this function to hit a key to continue by the                 */
/* user                                                                                    */
void getch() {
     __asm__ __volatile__ (
          "xorw %ax, %ax\n"
          "int $0x16\n"
     );
}

/* function to print a colored pixel onto the screen                    */
/* at a given column and at a given row                                 */
/* input ah = 0x0c                                                      */
/* input al = desired color                                             */
/* input cx = desired column                                            */
/* input dx = desired row                                               */
/* interrupt: 0x10                                                      */
void drawPixel(unsigned char color, int col, int row) {
     __asm__ __volatile__ (
          "int $0x10" : : "a"(0x0c00 | color), "c"(col), "d"(row)
     );
}

/* function to clear the screen and set the video mode to               */
/* 320x200 pixel format                                                 */
/* function to clear the screen as below                                */
/* input ah = 0x00                                                      */
/* input al = 0x03                                                      */
/* interrupt = 0x10                                                     */
/* function to set the video mode as below                              */
/* input ah = 0x00                                                      */
/* input al = 0x13                                                      */
/* interrupt = 0x10                                                     */
void initEnvironment() {
     /* clear screen                                                    */
     __asm__ __volatile__ (
          "int $0x10" : : "a"(0x03)
     );
     __asm__ __volatile__ (
          "int $0x10" : : "a"(0x0013)
     );
}

/* function to print rectangles in descending order of                  */
/* their sizes                                                          */
/* I follow the below sequence                                          */
/* (left, top)     to (left, bottom)                                    */
/* (left, bottom)  to (right, bottom)                                   */
/* (right, bottom) to (right, top)                                      */
/* (right, top)    to (left, top)                                       */
void initGraphics() {
     int i = 0, j = 0;
     int m = 0;
     int cnt1 = 0, cnt2 =0;
     unsigned char color = 10;

     for(;;) {
          if(m < (MAX_ROWS - m)) {
               ++cnt1;
          }
          if(m < (MAX_COLS - m - 3)) {
               ++cnt2;
          }

          if(cnt1 != cnt2) {
               cnt1  = 0;
               cnt2  = 0;
               m     = 0;
               if(++color > 255) color= 0;
          }

          /* (left, top) to (left, bottom)                              */
          j = 0;
          for(i = m; i < MAX_ROWS - m; ++i) {
               drawPixel(color, j+m, i);
          }
          /* (left, bottom) to (right, bottom)                          */
          for(j = m; j < MAX_COLS - m; ++j) {
               drawPixel(color, j, i);
          }

          /* (right, bottom) to (right, top)                            */
          for(i = MAX_ROWS - m - 1 ; i >= m; --i) {
               drawPixel(color, MAX_COLS - m - 1, i);
          }
          /* (right, top)   to (left, top)                              */
          for(j = MAX_COLS - m - 1; j >= m; --j) {
               drawPixel(color, j, m);
          }
          m += 6;
          if(++color > 255)  color = 0;
     }
}

/* function is boot code and it calls the below functions               */
/* print a message to the screen to make the user hit the               */
/* key to proceed further and then once the user hits then              */
/* it displays rectangles in the descending order                       */
void main() {
     printString("Now in bootloader...hit a key to continue\n\r");
     getch();
     initEnvironment();
     initGraphics();
}

Next, create a linker file test.ld with the following content:

ENTRY(main);
SECTIONS
{
    . = 0x7C00;
    .text : AT(0x7C00)
    {
        *(.text);
    }
    .sig : AT(0x7DFE)
    {
        SHORT(0xaa55);
    }
} 

Then use the following commands:

gcc -c -g -Os -m32 -ffreestanding -Wall -Werror test.c -o test.o

ld -m elf_i386 -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o

objcopy -O binary test.elf test.bin

bochs

However, when I typed in the second command "ld -m elf_i386 -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o", the output was:

ld: section .sig LMA [0000000000007dfe,0000000000007dff] overlaps section .eh_frame LMA [0000000000007d58,0000000000007e47]

The tutorial provides three other c source codes that do simpler things such as print "X" and "hello world" and I had no problem running them. I thought maybe it happened because there was too much contents in the c source code, so I tried changing the starting point of .sig section. But bochs said "no bootable device". Then I tried to erase the ehfram section by adding "-fno-asynchronous-unwind-tables" to the second command(linker). But it still says "no bootable device". What should I do to make bochs run it properly?

Community
  • 1
  • 1
pxc3110
  • 243
  • 3
  • 14
  • 1
    I would say, just get rid of `ehframe` section as suggested [here](https://stackoverflow.com/questions/26300819/why-gcc-compiled-c-program-needs-eh-frame-section). – Eugene Sh. Jul 27 '17 at 14:18
  • @EugeneSh. I added the flag "-fno-asynchronous-unwind-tables" to the linker command but it still says "no bootable medium" – pxc3110 Jul 27 '17 at 14:30
  • This is a completely different issue, don't you think so? – Eugene Sh. Jul 27 '17 at 14:33
  • @EugeneSh. Isn't that what the user "R.." says, add the flag to elimate ehframe section – pxc3110 Jul 27 '17 at 14:37
  • The "no bootable medium" is not a linker message, is it? – Eugene Sh. Jul 27 '17 at 14:48
  • @EugeneSh. It's not. But my question is "What should I do to make bochs run it properly? " – pxc3110 Jul 27 '17 at 14:51
  • No, this question is too broad and not appropriate. You have several completely different issues, and most of the information in the question is related to the linking, which I believe is resolved now. The other issues seem to be related to the internals of the implementation and should be more localized and asked in different question. – Eugene Sh. Jul 27 '17 at 14:53
  • I'll make edit to my question tomorrow. Have to go to bed now, see you tomorrow. – pxc3110 Jul 27 '17 at 14:55
  • @EugeneSh. My bad. adding -fno-asynchronous-unwind-tables" didn't yield anything but instead it said "ld: -f may not be used without -shared" and I was justing testing the old binary file which weren't updated at all. So, what does "-f may not be used without -shared" mean? What next? – pxc3110 Jul 29 '17 at 11:38

0 Answers0