c++ - 在 Linux 上同时使用 ORG 和 EXTRN 进行组装
问题描述
我一直在寻找编写引导加载程序的指南。
原文: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 语法而不是 MASM 语法的修改后的 .asm 文件:
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,
0,
0,
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;
}
解决方案
推荐阅读
- protractor - 如何修复“错误:getaddrinfo ENOTFOUND selenium-release.storage.googleapis.com selenium-release.storage.googleapis.com:443”
- ruby-on-rails - Ruby on Rails 添加评论以发表
- vhdl - VHDL 中带有 MPU6050 的 I2Cmaster 无法正常工作
- sql - 删除选择中的重复项
- reactjs - react redux - 重置其他状态
- json - 我如何知道 JSON 字符串包含一个没有提供任何键的数组(在 Java 中)?
- wordpress - 如何在主页上调用自定义帖子类型的 ACF 字段
- angular - 想要使用 Angular 6 和路由根据下拉值显示组件
- c# - 在按钮或框架内显示小图像
- npm - `npm outdated -g` 不起作用,发生错误