My second RetroChallenge task this month is to attempt to boot a Tandy 1000HX from scratch. When I say I plan to boot it from scratch, I’m actually talking about writing boot code, copying the compiled code to the boot sector, and successfully getting the Tandy to run said code without using MS-DOS. This task might seem pointless to some, especially since the 1000HX ships with MS-DOS in ROM, but most of RetroChallenge is rather pointless.
The Tandy 1000 HX, which I used during the Winter Warm Up, is an odd all-in-one machine. The keyboard, motherboard, and 720KB 3.5 inch floppy drive are all housed in a single unit. The system itself is powered by an 8088 CPU, and my system has a full 640KB RAM. The Tandy 1000 series is especially interesting as they are IBM PCjr clones, not strictly PC clones. This slight differentiation can lead to minor difficulties, but it shouldn’t affect my quest to successfully boot the system.
I personally have been interested in writing simple boot code since it is the basis for constructing an operating system. As a teenager, I always thought authoring an operating system would be sweet, but I never had the knowledge and skills. However, these days, after years of participating in development projects, I still don’t possess the knowledge and skills. As an alternative, I’m attempting to write simplistic boot code.
The boot process of an IBM clone is rather simple. When booting from a floppy disk, the BIOS loads in the first sector of the floppy, measuring 512 bytes, and stores the code at memory address 0×7C00. If the sector ends in two specific bytes (0×55AA), the sector is identified as bootable, and the code present within the sector is executed. Rather simple, right?
Because only 512 bytes are available, the code for the boot sector is usually written in assembly. For a true operating system, the code normally loads in more substantial code and data from the floppy disk, which the original boot code subsequently executes. This additional code does not have any limitaitons, and would often be the operating system itself.
That said, the 512 bytes can also be written to do something interesting. My goal was to start with this simple task of creating a usable 512 byte boot sector. Searching online revealed a dated article on creating said code, available here. The suggested code is a simple bit of assembly that should, in theory, display an “A” on a blue background in the upper left-hand corner:
entry start
start:
mov ax,#0xb800
mov es,ax
seg es
mov [0],#0×41
seg es
mov [1],#0×1f
loop1: jmp loop1
This example is moderately easy to follow. The second two lines set the current segment to 0xb800, the address where video RAM begins. The “seg es” directives notify the compiler that the following statement are going to use the segment (0xb800) stored in the ES register. The “mov [0],#0×41” code puts the captial “A” at memory location zero, or the first byte in video RAM. The second similar move instruction sets the appropriate attribute. Finally, a loop at the end is basically used to lock up the machine infinitely.
The big problem with the example is that the code is written for the as86 assembler, available on GNU/Linux. After installing as86, I compiled the code and wrote the resultant 24 bytes into the first 24 bytes of a FreeDOS boot floppy. The resultant image is actually bootable on VirtualBox, which is quite amazing. However, I had hoped to work on a DOS system, my 486, as a development machine using TASM or MASM. The code as is does not compile under either commercial assembler. Specifically, the “seg es” lines are not supported by the compilers, and the directives that set the letter “A” and its attributes generate an error. I tried yesterday and the day before to rewrite this handful of code to work with either MASM or TASM, but I failed miserably due to my lack of assembly language knowledge.
Today I gave in and transfered the as86-generated code to an actual 720KB floppy’s boot sector. While I was worried that as86 might not be generating true 8088-compatible code, I was surprised to find an “A” on a blue background in the upper left corner of the screen.
My next goal was to possibly find an example written in some assembly syntax that is slightly more widespread in use. Searches for “MASM boot sector” and TASM boot sector were relatively fruitless until I happened upon a similar set of instructions from a document on textfiles.com. This document suggested the Turbo Assembler, TASM, as an option, but the code, sadly, was directed at NASM, the Netwide Assembler. As NASM isn’t a historical DOS assembler in my mind, I had avoided it. However, out of deep frustration, I decided to use it once I saw that a version for MS-DOS existed.
The new example is somewhat different than the original, shorter example in that it uses BIOS calls to achieve screen IO:
START:
MOV AX,0x0003
INT 0x10
PRINT_STRING:
MOV AX,0x1301
MOV BX,0x0007
MOV CX,0x23
MOV BP,MSG
ADD BP,0x7C00
INT 0x10
WAIT_FOR_KEY_PRESS:
MOV AH,0x00
INT 0x16
REBOOT:
DB 0xEA
DW 0x0000
DW 0xFFFF
MSG DB 'Press any key...',13,10
TIMES 510-($-$$) DB 0
SIGNATURE DW 0xAA55
My version that I implemented at this point is actually wrong. Specifically, I neglected to terminate the message string. When I boot this code on the Tandy, I get no text at all. However, the keyboard input and subsequent reboot work perfectly. I must admit, though, that I don’t yet have a good handle on everything occurring in this implementation.
The last implementation should be an acceptable starting point. My lack of assembly is really hurting me at this point, but I should be able to pick up enough to make this challenge interesting.
Tags: Vintage Computing // Add Comment »