I have been coding for FreeDOS some time, but that is a C project and I
rather hate C. It is so clumsy. That's also why I always code in A86
assembly language. The "No Red Tape" assembler that makes life a lot
easier for programmers.
A86 is good. The debugger (D86) could be better, but not too much. I
registered my version and I want to encourage everyone to follow my
lead. The software is good enough to pay for it. And it ensures proper
development of the software. If you can spare 20 bucks a month for the
ISP, you should also spend this on quality software.
During the last two years I have been submiutting bugs to Isaacson and
all of them have been fixed in the latest version (4.03).
Besides A86 being the best assembler around, it has some idiosyncracies
to which some people need to get used to. Plus my personal preferences,
which might add to that...
- When I refer to a memory location I use square brackets.
- I use single quotes for texts
- I use most of the A86 features.
Some of the A86 features are:
- very powerful macro language
- numbers starting with a ZERO are ALWAYS hex, no matter how they end
- easy IF statements to reduce nonsense labelnames
- local labels, like below: only two local labels.
I started out on the Z-8000, back in 1981, switched to the Z-80, Z-8,
8086, PIC 16Cxx, some 8051 (Barffff), some 68K (yummie yummie). Mainly
in ASM and else in Modula-2. I have some really cool and useful routines
lying around for DOS. And I'm gonna share them with the world.
The following code is a bootsector which can be used for noon-bootable
disks. In this case for a 1.44 Mb floppy disk. You could use it to make
a commercial out of every non-bootable disk.
First the code:
----- Code file -------------------------------------------------
name flopnb
title Floppy disk boot sector, non-bootable, 1.44 Mb
page 80, 120
; version 1.0 : It works : OK 12-12-1998
lf = 10
cr = 13
org 0
jmp short main ; this is critical!
nop ; and this too!
; ----------------------
OEMname db 'StupiDOS'
BpS dw 512 ; bytes per sector
SpA db 1 ; sectors per allocation unit (=cluster)
ResSect dw 1 ; reserved sectors, starting from sector 0
NrFats db 2 ; number of FAT's on this disk
FiR dw 224 ; number of entries in ROOT directory
Total dw 2880 ; number of sectors per disk
ToM db 0F0 ; Type of Media
SpF dw 9 ; Sectors per Fat
SpT dw 18 ; sectors per Track
Heads dw 2 ; number of heads
Hidden dw 0, 0 ; Hidden sectors
GrandTot dd 0 ; total for disks over 32 Mb
IntId db 0, 0
BootSign db 029 ; extended boot signature
VolumeID dd 0566E614A ; serial number ...
DiskLabl db 'DOS is MINE' ; volume label
FATtype db 'FAT-12 ' ; FAT type
db 'VeRsIoN=1.0', 0 ; for version control only
; ----------------------
L1: push si ; stack up return address
ret ; and jump to it
print: pop si ; this is the first character
mov bx, 0 ; video page 0
L0: lodsb ; get token
cmp al, 0 ; end of string?
je L1 ; if so, exit
mov ah, 0E ; else print it
int 010 ; via TTY mode
jmp L0 ; until done
; ----------------------
main: cld ; init direction flag
cli ; take care of 1 faulty batch of 88's in 1980
mov ax, 07C0 ; this is the segmentvalue at start
mov ds, ax ; store it in DS, ES
mov es, ax
mov ax, 0 ; clear ax ...
mov ss, ax ; ... to prime the SS register
mov sp, 07C00 ; set stackpointer
sti ; OK, interrupts may come again
call print ; show that message
db cr
db 'This is not a bootable floppy. '
db 'Please strike any key to reboot.', cr, lf
db 'This floppy disk is formatted by FreeDOS', cr, lf, lf
db 'Please visit us at www.freedos.org', cr, lf, 0
L0: mov ah, 1 ; wait for keypress by ...
int 016 ; ... interrogating keyboard
jz L0 ; if no key pressed, loop back
mov ax, 0 ; else address system variables
mov es, ax ; in order to ...
es mov w [0472], 01234 ; signal: NO POST and go on ...
jmp 0FFFF:0000 ; with the next reboot
org 01FE ; look for the dotted line and ...
db 055, 0AA ; ... don't forget to sign!
------------------------------------------------- Code file -----
The first three lines are straightforward: name, title and page. Not
much to tell about that. Then some version info for the programmer, some
equates and the ORG statement.
If no ORG is supplied, A86 will assume it is ORG 0100. I ordered an ORG 0,
which means several things:
- start assembly at address 0
- the output file will be called *.BIN
Bootsectors must start with some particular bytes. Therefore the first
three bytes need to be either a short jump, a variable offset plus a
NOP. Or a (long) jump without a NOP.
At offset 03 of the bootsector starts the DPB (Disk Parameter Block)
which tells the OS what kind of disk this is. It starts off with an OEM
name. Please put ASCII in there, or virus scanners might trip on it with
a "Bloodhound warning".
After the description of the geometry of this disk, I included an
extended boot signature, since we have ample room left. It contains
Volume ID, Disk Label, and FAT-type strings.
The PRINT subroutine is a nice one. It will print the ASCIIZ string that
follows it. This is quite a handy routine since you can simply change
messages without having to worry about the address and length of the
actual message.
Print is called like this:
call print
db 'Hello World', cr, lf, 0
...
Print takes the "return address" off the stack. This of course is no
return address but the address of the message. What follows is easy:
- get next character
- IF (non-zero) print character ELSE leave loop ENDIF
- the current si pointer is the actual return address... So we push it
- and return to caller.
Perhaps a jmp si could be possible too, but I like clear code, in most
cases. If you need obfuscated code, switch to C. :)
The actual program is very simple. It just sets up a stack and the
segment registers, and then prints that it will do nothing. Gee, what a
life...
After the message we wait for a key and next signal:
- fast reboot
- jump to the reboot vector
Whatever there will be between end of code and offset 01FE is not
relevant (it could be your ad) but the last two bytes of the boot sector
must be a valid boot signature.
That's it. With this code you can make your own custom non-bootsector.
I hope this software has also shown that linking and assuming are
supported by A86, but certainly not necessary. Also, this software does
not rely on any HLL calls. It's just assembly language as it should be.
I want to remark that this software is Open Source, according to the rules
of the GNU GPL. Make sure you understand these rules before embedding this
routine in your own software.
|