返回

文章详情

从零开始在Behringer DDX3216上运行DOS的DIY x86 BIOS

Hacker News2026年6月13日 18:32

在1994年,我得到了我的第一台电脑:一台Intel i486 DX2-66,配有4MB RAM和512MB硬盘。操作系统是IBM的OS/2和微软的Windows 3.11。在接下来的四年中,我每隔几个月就对这台机器进行了升级,增加了更多的RAM(最高可达16MB)、CD-ROM驱动器和Soundblaster声卡。因此,我学会了如何升级这台机器、安装新软件,并最终学习如何使用BASIC编写新软件。但我从未接触过引导过程或MS-DOS的细节。在2026年,32年后,我从DDX3216的一些截图中得知,Behringer在这台机器中使用了一颗真正的386处理器。立刻,我脑海中的神经元开始活动,我思考是否可以在这个设备上引导软件甚至完整的操作系统。我的目标是学习x86系统是如何引导的,DOS是如何接管的,以及进入Shell所需的条件。目录 Behringer DDX3216的技术细节 自主开发裸机x86软初步步骤 使LCD正常工作并与段进行斗争 为SC300实施功能齐全的x86 BIOS 中断功能以及尝试引导MS-DOS 6.22 成功引导FreeDOS v1.4 更多内部硬件和下一步 Behringer DDX3216的技术细节 DDX3216使用以下硬件组件: 主处理器:AMD Elan SC300 386 SoC(带集成UART、PCMCIA、GPIO等的386SX) 27C512 64k x 8bit ROM芯片(用于BIOS) 8个HYB5117400BJ60 4M x 4bit RAM,总共16MB DRAM 1个UM61256 SRAM(作为视频RAM) 4个29C040-120 Flash-IC,供主软件使用 4位LCD,插入SC300内部LCD接口(配有3个Toshiba T6A39列控制器和1个T6A40行控制器) Toshiba TLC16C552外部UART(2个串口和1个并口) PCMCIA连接器用于外部CF卡连接(带适配器) 未组装的Intel 82078 FDC(软盘控制器),连接到备用的34针连接器 所以总的来说,围绕AMD Elan SC300的硬件相当不错,应该与普通的x86系统兼容。让我们深入了解x86系统的细节。 对于大多数计算机,您可以从互联网上下载现成的BIOS。因此,我寻找AMD ELAN SC的BIOS,并在瑞士找到了一个有前途的设备:PC Engines公司为AMD ELAN SC400和520以及一些其他SoC设备开发了BIOS程序。因此,我联系了主要开发者,起初他给了我一个有前途的答案,说他仍然有SC300的源代码。但是几天后,他不得不承认,他只有SC400及以上的源代码。我的下一个尝试是联系提供“嵌入式BIOS”的“General Software”公司,该公司支持SC300。但General Software成立于1989年,于2008年被Phoenix收购。因此,我与Phoenix在德国的一位负责人员联系。他试图获取有关兼容SC300的BIOS包的信息,但几周后,他不得不告诉我,这已经不可能了——32年是很长的时间。因此,我挽起袖子,开始阅读关于x86系统的一些文档,并做了关于为SC300编程自己的BIOS的一些笔记。即使是最现代的x86兼容CPU(如Intel的Core i9或AMD的Threadripper)也具有8086兼容的引导过程。在复位之后,CPU跳转到内存空间的结尾,即位置0xFFF0,并期待在这里找到一些可执行的x86代码——所谓的复位向量。从这个复位向量,我们必须跳转到下一个要执行的目标代码——在BIOS的ROM某处。以下是我实现有效x86复位向量的尝试: ASM 复位向量: nop // 无操作 cli // 禁用中断 jmp start // 跳转到当前段的开始 // 填充到末尾并添加日期 .zero ( 0x10 - (. - reset_vector) - 8 ) .ascii " 06 / 04 / 26 " // MM/ DD / YY 这段代码禁用硬件中断,然后跳转到start函数中的更多代码。通过执行这个跳转命令,CPU离开启动状态,进入所谓的“实模式”,这是8086的原始16位模式。复位向量的代码由链接脚本放置在最终ROM的0xFFF0位置。如上所示,DDX3216使用64k x 8bit ROM芯片,因此代码和数据可以存储在0x0000和0xFFFF之间,而复位向量必须放置在0xFFF0以兼容x86规范。以下是链接脚本,告诉GCC如何在最终二进制文件中放置代码: Plaintext OUTPUT_FORMAT("elf32-i386") OUTPUT_ARCH(i386) ENTRY(reset_vector) MEMORY { ROM (rx) : ORIGIN = 0x0000, LENGTH = 64K } SECTIONS { .text : { __text_start = .; KEEP(*(.text)) *(.text.*) . = ALIGN(2); __text_end = .; } > ROM .reset 0xFFF0 : { KEEP(*(.reset)) } > ROM } 最后,编译后的二进制文件如下: Plaintext 0000ffa0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0000ffb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .......

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡