使用打开的 watcom 为 286 cpu 编译引导加载程序

问题描述 投票:0回答:1

我正在尝试为我的旧 286 构建一个小型引导加载程序/程序。我开始使用 fasm 进行此操作,但很快就厌倦了编写汇编。所以我想我想用 c 语言来编写它,但是针对 286 的 c 工具链的选择似乎很少。我选择开放 watcom 1.9。到目前为止,我设法编译了一些东西,但是输出被破坏了,我不知道为什么。

init.asm,为兼容watcoms汇编器而编写,初始化寄存器,跳转到c函数kernelMain并提供简单的打印函数:

.code INIT
extern kernelMain_ : proc

org 7c00h

;export functions
PUBLIC initMain
PUBLIC _print
initMain:
;init stack to use the 30kb before this boot sector
;init other segment registers
mov bp,7C00h ; stack base pointer
xor ax,ax ; ax = 0
mov ds,ax ; data segment = 0
mov es,ax ; extra segment
mov ss,ax ; stack segment = 0
mov sp,bp ; stack pointer = 7C00h

jmp kernelMain_

;void __cdecl print(char* message, unsigned char length);
_print:
  pop si ; message
  pop cx ; length

printLoop: ; print string which is at adress si with length cx
  mov ah,0Eh ; TTY output function number
  mov bh,0 ; page 0
  mov bl,01h ; foreground color
  lodsb ; loads byte from [si] into al and advances pointer in si by 1
  int 10h ; BIOS video interrupt, write byte to screen
  loop printLoop ; loop till message is printed
  ret

end

test.c,包含kernelMain函数:

extern void __cdecl print(char* message, unsigned short length);


void kernelMain(void)
{
  print("this is a test", 14);
}

这就是我用来构建它的

wasm -2 -ms init.asm
wcc -2 -d0 -wx -ms -s -zl test.c
wlink file init.obj file test.obj format raw bin name test.bin option NODEFAULTLIBS,verbose,start=initMain ORDER clname CODE segment INIT

生成的二进制文件约为 32KB,而不是预期的几个字节,因为链接器解释 org 指令,实际上在代码之前用 0 字节填充所有内容。在代码完全破坏代码之前删除 0 填充。它不打印任何东西。删除 org 指令会给我执行和打印的代码,但它也会在测试消息之前打印出一些随机垃圾

有人可以帮助我吗?

c bootloader watcom 80286
1个回答
1
投票

感谢评论者,我现在得到了我想要的。

修复:

  1. 放弃将asm与c代码分开的想法,只使用c进行内联汇编
  2. 从此处升级以打开 watcom 2.0 beta https://github.com/open-watcom/open-watcom-v2/releases(当前版本包含版本和安装程序)
  3. 添加offset=0x7c00选项

测试.c:

void kernelMain(void);
void initasm(void);
#pragma aux initasm = \
"mov bp,7C00h", \
"xor ax,ax", \
"mov ds,ax", \
"mov es,ax", \
"mov ss,ax", \
"mov sp,bp", \
"jmp kernelMain" \
modify [ AX ];

void __pascal print(char* message, unsigned short length);
#pragma aux print = \
"pop cx", \
"pop si", \
"printLoop:", \
"mov ah,0Eh", \
"mov bh,0", \
"mov bl,01h",\
"lodsb", \
"int 10h", \
"loop printLoop" \
modify [ SI CX AH BH BL];

void init(){
  initasm(); //jumps to kernelMain after initializing registers. seperate init was necessary as adding any actual function calls (like print) would add push instructions before the inline assembly which would be called before initializing the stack and registers
}

void kernelMain(void)
{
  print("this is a test", 14);
}

构建测试.bat:

wcc -2 -d0 -wx -ms -s -zl test.c
wlink file test.obj format raw bin name test.bin option NODEFAULTLIBS,verbose,start=init_,OFFSET=0x7C00

这给了我一个链接在地址 0x7c00 的原始二进制文件。

要制作可写入软盘(或被虚拟机用作软盘)的可引导扇区,您必须将文件的其余部分填充到 510 字节长度,并添加 0x55 0xAA 作为最后 2 个字节,(总共 512 字节),将其标记为可引导扇区。

备注:如果作者(我)实际上可以编写正确的汇编,那么单独的 asm 和 c 的东西可能仍然会按预期工作

© www.soinside.com 2019 - 2024. All rights reserved.