在 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 语法中修改后的 .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 (将#修改为@)