我正在按照指南创建一个在此网页上绘制矩形的引导程序:https://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
首先,我需要创建test.c并复制以下源代码:
/* 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();
}
接下来,使用以下内容创建一个链接器文件test.ld:
ENTRY(main);
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00)
{
*(.text);
}
.sig : AT(0x7DFE)
{
SHORT(0xaa55);
}
}
然后使用以下命令:
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
但是,当我输入第二个命令“ld -m elf_i386 -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o”时,输出为:
ld:section .sig LMA [0000000000007dfe,0000000000007dff]重叠部分.eh_frame LMA [0000000000007d58,0000000000007e47]
本教程提供了另外三个c源代码,可以执行更简单的操作,例如print“X”和“hello world”,运行它们没有问题。我想也许它发生了,因为c源代码中的内容太多,所以我尝试更改.sig部分的起点。但是bochs说“没有可启动设备”。然后我尝试通过在第二个命令(链接器)中添加“-fno-asynchronous-unwind-tables”来擦除ehfram部分。但它仍然说“没有可启动设备”。我该怎么做才能让bochs正常运行?