首页 > 解决方案 > 在 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;
}

标签: c++linuxnasmmasmfasm

解决方案


推荐阅读