1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
! This binary is for loading a dev86 a.out file from a floppy without
! a filesystem; to make a bootable disk just do:
!
! cat boot_fpy.bin monitor.out > /dev/fd0
!
! Warning: Disk errors currently cause a hang.
! The boot sector does not end with $AA55 this is not a problem
! with the BIOS but many boot managers will not boot it.
ORGADDR=0x0600
EXEADDR=0x06E0
LOADSEG=0x0080 ! Must be 512b aligned for DMA
.org EXEADDR-1
.byte 0xFF ! Marker
.org ORGADDR
entry start
public start
start:
mov ax,#$07C0 ! Relocate to ORGADDR
mov ds,ax
xor ax,ax
mov es,ax
mov cx,#256
mov si,ax
mov di,#ORGADDR
cld
rep
movsw
jmpi go,#0
go:
mov ds,ax ! Setup SP & S-regs
mov ss,ax
mov sp,#ORGADDR
mov ax,[a_text] ! How many sectors to load
mov cl,#4
shr ax,cl
mov bx,ax
mov ax,[a_data]
mov cl,#4
shr ax,cl
add ax,bx
add ax,#$1F
mov cl,#5
shr ax,cl ! ax = sectors to read
! This routine starts by loading one sector at a time, with most
! modern PCs the processor is fast enough to keep up with single
! sector reads, in reality an 8Mhz 286 can keep up!
! But occasionally some older machines have really poor BIOSes
! (Some modern ones too) so once we know how many sectors to read
! we switch to reading a track at a time. But we only try it once
! for each track, normally, as long as the load address is sector
! aligned, this will work every time but with some BIOSes we can't
! read a track without messing with the BPB so if the track read
! fails it's one try we fall back to sector reads.
!
! Overall this usually gives good performance, and with a BIOS that
! isn't completely broken and correctly formatted floppies will run
! at about 2.5 rotations per cylinder (1.25 per track). If you find
! your BIOS is one of the bad ones you'll have to format your disks
! to a 2:1 interleave.
!
! BTW: There are some versions of superformat that incorrectly
! calculate the inter-sector gaps and end up squeezing the sectors
! to the start of the track. This means that only a full track read
! is fast enough.
! AX = count of sectors
mov cx,#2 ! CX = First sector
mov bx,#LOADSEG ! ES:BX = Where to load
mov es,bx
xor bx,bx ! Initial offset
xor dx,dx ! DX = Drive 0
! ax=cnt, dl=drv, ch=*, dh=*, cl=sec, es:bx=buffer.
read_data:
mov si,ax ! Save big count.
xor ch,ch
xor dh,dh
mov maxsect,cl ! Save first sector.
load_loop:
mov di,#5 ! Error retry.
sect_retry:
mov ax,#$0201
! ah=2, al=1, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer.
int $13
jnc next_sect
dec di ! Retry counter
jz sect_error
cmp cl,maxsect ! If this is first sector or previously ok sector
jle sect_retry ! number then retry.
mov maxsect,cl
j inc_trk
next_sect:
mov ax,es ! Inc load address.
add ax,#32
mov es,ax
dec si ! Had enough ?
jz all_loaded
inc_sect:
inc cl
cmp cl,maxsect
jnz load_loop
inc_trk: ! Reached end of track, seek to next.
mov cl,#1
xor dh,cl
jnz load_track
inc ch
load_track:
cmp si,maxsect ! Is the whole track needed ?
jb load_loop ! no, goto load_loop for 1 by 1
! Try to load the track _once_ only, if it fails go 1 by 1 again.
mov ax,maxsect
dec ax
mov ah,#$02
! ah=2, al=*, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer.
int $13
jc load_loop
mov ax,maxsect ! Ok that worked, update the pointers
dec ax
mov cl,#5
shl ax,cl
mov di,es
add ax,di
mov es,ax
inc si
sub si,maxsect
jnz inc_trk
all_loaded:
xor dx,dx ! DX=0 => floppy drive
push dx ! CX=0 => partition offset = 0
mov si,dx ! Sect/track = 0
mov bx,#EXEADDR>>4
mov ds,bx ! DS = loadaddress
xor di,di ! Zero
mov ax,[di+2]
and ax,#$20 ! Is it split I/D ?
jz impure ! No ...
mov cl,#4
mov ax,[di+8]
shr ax,cl
impure:
pop cx ! Partition offset.
inc bx
inc bx ! bx = initial CS
add ax,bx
mov ss,ax
mov sp,[di+24] ! Chmem value
mov ds,ax
! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=*
bad_magic:
push bx ! jmpi 0,#LOADSEG+2
push di
retf
sect_error:
! TODO Error.
j sect_error
maxsect:
.word 0
! Check for overlap
end_of_code:
if end_of_code>hitme
fail! Overlap at end_of_code
endif
.org EXEADDR
hitme:
magic: .space 2 ! A.out header
btype: .space 2
headerlen: .space 4
a_text: .space 4
a_data: .space 4
a_bss: .space 4
a_entry: .space 4
a_total: .space 4
a_syms: .space 4
|