问题描述
我一直在寻找编写引导加载程序的指南。
原文:https://www.apriorit.com/dev-blog/66-develop-boot-loader
复制:https://www.codeproject.com/Articles/36907/How-to-develop-your-own-Boot-Loader
我喜欢他们采用的设计能够在 asm 中做到最低限度,然后使用 C/C++ 完成其余的工作。 (我敢肯定,如果事情更复杂,100% 编写良好 的程序集会更好,但这不是重点。)
我正在尝试在没有 MASM 的 Linux 上编译此代码。
我尝试使用 NASM(需要对源代码进行一些调整),但是在编译平面二进制文件时,您不能使用 EXTERN。当尝试使用某种目标文件格式时,您不能使用 ORG(因为他们不想要 MASM 允许的意大利面条代码)。但是,ORG 不是正常位置,而是在 0x7c00,因为这是 BIOS 的位置。
接下来我尝试了 FASM,它再次不允许 EXTRN 用于平面二进制文件,因此尝试使用 COFF 格式,我能够同时使用 ORG 和 EXTRN,但是,当我执行 call _BootMain
时,汇编程序抱怨“地址大小不一致”。我一直在寻找解决方案,但不知所措。
必须有一种方法可以将 C 代码与程序集混合在一起,并且仍然使用程序集来指定使用 Linux 的原始位置,我认为!?我真的不想为了做到这一点而求助于 Windows。我想我真的很接近 FASM。这是 FASM 语法中修改后的 .asm 文件,而不是 MASM 语法:
format COFF
use16
extrn _BootMain ; protype for C function
org 0x7c00 ; BIOS starts program at 0x7c00
main:
jmp near start
nop
start:
cli
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov bp,0x7c00
mov sp,0x7c00
sti
call _BootMain
ret
--- 如果两个网站都宕机,这就是教程使用的代码。 ---
;------------------------------------------------------------
.286 ; cpu type
;------------------------------------------------------------
.model TINY ; memory of model
;---------------------- EXTERNS -----------------------------
extrn _BootMain:near ; prototype of C func
;------------------------------------------------------------
;------------------------------------------------------------
.code
org 07c00h ; for BootSector
main:
jmp short start ; go to main
nop
;----------------------- CODE SEGMENT -----------------------
start:
cli
mov ax,cs ; Setup segment registers
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
mov ss,ax ; Make SS correct
mov bp,7c00h
mov sp,7c00h ; Setup a stack
sti
; start the program
call _BootMain
ret
END main ; End of program
// BootMain.cpp
#include "Cdisplay.h"
#define HELLO_STR "\"Hello,world…\",from low-level..."
extern "C" void BootMain()
{
Cdisplay::ClearScreen();
Cdisplay::ShowCursor(false);
Cdisplay::textout(
HELLO_STR,BLACK,WHITE,false
);
return;
}
// Cdisplay.h
#ifndef __CdisPLAY__
#define __CdisPLAY__
//
// colors for textout func
//
#define BLACK 0x0
#define BLUE 0x1
#define GREEN 0x2
#define CYAN 0x3
#define RED 0x4
#define magenta 0x5
#define broWN 0x6
#define GREY 0x7
#define DARK_GREY 0x8
#define LIGHT_BLUE 0x9
#define LIGHT_GREEN 0xA
#define LIGHT_CYAN 0xB
#define LIGHT_RED 0xC
#define LIGHT_magenta 0xD
#define LIGHT_broWN 0xE
#define WHITE 0xF
#include "Types.h"
#include "CString.h"
class Cdisplay
{
public:
static void ClearScreen();
static void textout(
const char far* inStrSource,byte inX = 0,byte inY = 0,byte inBackgroundColor = BLACK,byte inTextColor = WHITE,bool inUpdateCursor = false
);
static void ShowCursor(
bool inMode
);
};
#endif // __CdisPLAY__
// Cdisplay.cpp
#include "Cdisplay.h"
void Cdisplay::textout(
const char far* inStrSource,byte inX,byte inY,byte inBackgroundColor,byte inTextColor,bool inUpdateCursor
)
{
byte textAttribute = ((inTextColor) | (inBackgroundColor << 4));
byte lengthOfString = CString::Strlen(inStrSource);
__asm
{
push bp
mov al,inUpdateCursor
xor bh,bh
mov bl,textAttribute
xor cx,cx
mov cl,lengthOfString
mov dh,inY
mov dl,inX
mov es,word ptr[inStrSource + 2]
mov bp,word ptr[inStrSource]
mov ah,13h
int 10h
pop bp
}
}
void Cdisplay::ClearScreen()
{
__asm
{
mov al,02h
mov ah,00h
int 10h
}
}
void Cdisplay::ShowCursor(
bool inMode
)
{
byte flag = inMode ? 0 : 0x32;
__asm
{
mov ch,flag
mov cl,0Ah
mov ah,01h
int 10h
}
}
// CString.h
#ifndef __CSTRING__
#define __CSTRING__
#include "Types.h"
class CString
{
public:
static byte Strlen(
const char far* inStrSource
);
};
#endif // __CSTRING__
// CString.cpp
#include "CString.h"
byte CString::Strlen(
const char far* inStrSource
)
{
byte lenghtOfString = 0;
while(*inStrSource++ != '\0')
{
++lenghtOfString;
}
return lenghtOfString;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)