c# 编译bootloader与开放watcom为286 cpu

kx7yvsdv  于 2023-08-01  发布在  C#
关注(0)|答案(1)|浏览(264)

我试图为我的旧286建立一个小的 Bootstrap /程序。我开始用fasm做这件事,很快就厌倦了编写汇编。所以我想用c来写它,但是针对286的c工具链的选择似乎很小。我选择了Open 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


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

tp5buhyn

tp5buhyn1#

感谢评论者,我现在得到了我想要的。
修复:
1.放弃asm从c代码中分离的想法,只使用c与内联汇编
1.从这里升级到开放watcom 2.0测试版https://github.com/open-watcom/open-watcom-v2/releases(当前版本包含版本和安装程序)

  1. add 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);
}

字符串
buildtest.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的东西可能仍然会像预期的那样工作,如果作者(我)实际上可以编写正确的汇编

相关问题