-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGETCD.ASM
268 lines (237 loc) · 11.2 KB
/
GETCD.ASM
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
;GETCD V 1.0 | 3-NOV-2024 Jay Moore/dewdude@pickmy.org
;Finds CDROM drive letter and places in CDROM
;environment variable
;
;A replacement for FINDCD.EXE written in NASM Assembly and
;manipulates a lot of memory directly. Not a drop-in
;replacement, but close. Designed as a .BAT utility, the
;only user interaction is feeding it a path/filename and
;checking the environment variable. Default returns first
;CDROM drive that has a disc.
;
;GETCD [/?] SEARCHSTRING
;
;SEARCHSTRING can be a file, directory name, path, or wildcard.
;Not specifying a file does a wildcard search on root of CD.
;You do not need to add a leading \ to the string.
;/? displays the usual help, except poorly written.
;
;CDROM=E:
;
;Is how the variable will be set. If you desire a trailing \;
;just have your script 'set CDROM=%CDROM%\'
;
;This will absolutely overwrite any existing CDROM= contents with
;the above format; and will also shift data around to make it the
;exact length. It will also create an environment variable if none
;exists. This is contrast with FINDCD.EXE; which not only needs
;you to set the CDROM= variable first, but requires patching the
;.exe to change the file search. Gross.
;
;Displayed output is minimal. The only error displayed is if the
;environment block is full. A lack of CDROM drives will exit with
;errorlevel 255. Anything else just doesn't change (or create) the
;CDROM variable. You'll need to do that after execution in your script.
;
;argument section of PSP starts at 80h; byte count, bytes, terminator.
;term is 0x0D, but it's not included in byte count. this can include
;spaces if full name.ext is used or user just hit space.
;the pointer to parent's PSP lives at 16h; env-block pointer is 2Ch
;offset 3 one segment back is the block allocation size.
;this means I initialize di to 10h now and just leave es where it is
;as all counts are relative from di's initialization
[CPU 8086]
[BITS 16]
org 100h
section .text
global start
start:
xor cx, cx ; clear out cx
mov si, 80h ; move si to psp argument count
mov cl, [si] ; load argument byte count
argproc:
jcxz varinit ; stop if cx is 0
inc si ; increment si
cmp byte [si], 20h ; Invalid char/space check
jbe skipit ; jump to loop if <20h
cmp byte [si], 5ch ; is it backslash
jz skipit ; jump if it is
cmp word [si], 3f2fh ; check for /?
jz hllp ; jump if it is
jmp ldfile ; land here when done
skipit:
loop argproc ; dec cx, jmp argproc ;)
ldfile:
lea di, filename ; load filename to di
repe movsb ; copy argument to filename
mov byte [di], 0 ; null for good measure
varinit:
mov es, [16h] ; parent psp pointer
mov ax, [es:2ch] ; load block segment
dec ax ; segment one below
mov es, ax ; go back a segment
mov ax, [es:3h] ; this is the size
mov cl, 4 ; load 4 to cl for shl
shl ax, cl ; bit shift left 4
mov [blocksize], ax ; store
mov di, 10h ; move di up to env blk
readblock:
cmp word [es:di], 0 ; end of block?
jz endofblock ; variiable missing
lea si, envname ; load envname address
mov cx, 6 ; load six
repe cmpsb ; repe compare string
jnz readblock ; if not variable, go back up
sub di, 6 ; subtract 6
mov [envstart], di ; write starting location
add di, 6 ; place it back
findend:
inc di ; now to find the end
cmp word [es:di], 0 ; is it the end?
jnz findend ; jump back up if not
endofblock:
inc di ; actual end of block
mov [blockend], di ; write that down
cmp word [envstart], 0 ; did we find a var
jz noenv ; jump if novar
mov di, [envstart] ; go back to the env start
mov ax, 1212h ; get the asciz length
int 2fh ; in to cx
cmp cx, 9 ; and see if it's 9
jb envtoosmall ; jump to envtosmall if too small
ja envtoobig ; jump to envtoobig if too big
envokay:
add di, 6 ; drive letter is six in
jmp drivego ; es:di ready for letter
envtoobig:
mov si, di ; duplicate pointers
mov word [es:di+7], 0x003A ; write : and null
add si, 9 ; put si where i need di
call endcheck ; check relative position
call bytesize ; get byte count to copy
xchg di, si ; now we swap
cld ; clear that direction
call copybytes ; copy byte routine
mov word [es:di], 0 ; double null new end
mov di, [envstart] ; go back to the env
jmp envokay ; might as well jump
noenv:
call envfree ; check free space
mov di, [blockend] ; go to block end
newenv:
lea si, envname ; load address of envname
mov cx, 8 ; we want 8 bytes
repe movsb ; write 'em
mov word [es:di], 0000h ; double null new term
sub di, 2 ; back di up two
jmp drivego ; es:di is ready
envtoosmall:
mov byte [oneornine], 01h ; change envfree's cmp value
call envfree ; check environment space
call endcheck ; check relative position
call bytesize ; call for byte count
add cx, 3 ; add three to that count
mov si, [blockend] ; load the end of block offset to si
mov di, [blockend] ; load it again to di
inc di ; move it up one
std ; set direction flag
call copybytes ; copybytes routine
mov word [es:di+1], 0x003A ; write the : and null one byte up
drivego:
mov ax, 2524h ; Ignore Critical Errors
lea dx, [new24] ; pointer to new handler
int 21h ; interrupt to change ivt
mov ax, 1500h ; function to get drive info
int 2Fh ; from int 2f
xchg bx, cx ; swap count and starting number
jcxz nodrives ; see if we have drives
add bl, 41h ; convert number to letter
loadltr:
push cx ; push drive count to stack
mov [drivevar], bl ; copy drive letter to ram
lea dx, drivevar ; load address of drivevar
mov ah, 4Eh ; load find first file
mov cl, 17h ; all the options
int 21h ; call the interrupt
jnc envset ; found file, go on
pop cx ; pop drive count back in to CX
inc bl ; increment to next drive
loop loadltr ; loop back around
jmp exit ; no match, leave
envset:
lea si, drivevar ; loads address to si
movsb ; moves ds:si to es:di
jmp exit ; we're done, go home
nodrives:
mov al, 0FFh ; load errorlevel 255 to al
exit:
mov ax, 4c00h ; standard dos kernel terminate
int 21h ; bye.
endcheck:
push cx ; push cx to stack
add cx, di ; add di to cx
sub cx, [blockend] ; subtract blockend from cx
jcxz fakenew ; jump if zero
pop cx ; invert cx (it should be neg)
ret ; go back to moving bytes
fakenew:
sub sp, 04h ; reset the stack you animal
mov di, [envstart] ; load di
jmp newenv ; pretend it's new
copybytes:
push ds ; push ds on to the stack
push es ; push es on to the stack
pop ds ; pop es in to ds for this
repe movsb ; copy ds:si to es:di till cx is 0
pop ds ; pop ds's original value back out
ret
envfree:
mov ax, [blocksize] ; load size
sub ax, [blockend] ; calculate free
cmp al, [oneornine] ; need n free
jz blockfull ; not enough space
ret ; return if ok
bytesize:
add di, cx ; place di at next variable
mov cx, [blockend] ; load the end of the block
sub cx, di ; subtract the actual usage
ret ; return from subroutine
hllp:
lea dx, hlptxt ; address of $-terminated strong
mov ah, 09h ; display string function
int 21h ; dos interrupt
jmp exit ; exit
new24:
mov al, 3 ; FAIL! (Hitting F, but faster)
iret ; Return from interrupt.
section .data
hlptxt:
db 'GETCD 1.0 | 4-NOV-2024 | dewdude@pickmy.org | Freeware/MIT', 0x0d, 0x0a
db 'Sets "CDROM=[driveletter]:" by searching CD-ROM drives', 0x0d, 0x0a
db 'USAGE: GETCD [/?] [FILE/OR/PATH/TO/FILE.EXT]', 0x0d, 0x0a
db 'Finds file on CD-ROM drives. Returns first match. Allows wildcards.', 0x0d, 0x0a
db 'Creates/adjusts variable. Default search is wildcard.$', 0x0d, 0x0a
blockfull: db 'NO ENV FREE $'
blocksize: db 0, 0 ; holds block size
envstart: db 0, 0 ; start of cdrom=
blockend: db 0, 0 ; end of used block
oneornine: db 09h ; default 9
envname: db 'CDROM=' ; variable name
drivevar: db '0:\' ; variable's variable
filename: db '*', 0x00 ; (default) filename
;MIT No Attribution
;
;Copyright 2024 Jay Moore
;
;Permission is hereby granted, free of charge, to any person obtaining a copy of this
;software and associated documentation files (the "Software"), to deal in the Software
;without restriction, including without limitation the rights to use, copy, modify,
;merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
;permit persons to whom the Software is furnished to do so.
;
;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
;INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
;PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
;OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.