1 | ; $Id: kRxa.asm,v 1.1 2000-06-03 03:50:45 bird Exp $
|
---|
2 | ;
|
---|
3 | ; kRxa - Small rexx script interpreter.
|
---|
4 | ;
|
---|
5 | ; Assembly edition.
|
---|
6 | ;
|
---|
7 | ; Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
|
---|
8 | ;
|
---|
9 | ; Project Odin Software License can be found in LICENSE.TXT
|
---|
10 | ;
|
---|
11 |
|
---|
12 |
|
---|
13 | .386p
|
---|
14 | .model flat
|
---|
15 | .stack 10000h
|
---|
16 |
|
---|
17 | ;DEBUG EQU 1
|
---|
18 |
|
---|
19 | ;
|
---|
20 | ; External Functions
|
---|
21 | ;
|
---|
22 | extrn DosWrite:PROC
|
---|
23 | extrn RexxStart:PROC
|
---|
24 |
|
---|
25 |
|
---|
26 | ;
|
---|
27 | ; Defined Constants And Macros
|
---|
28 | ;
|
---|
29 | MAX_ARG_LENGTH EQU 1000h
|
---|
30 |
|
---|
31 | ;
|
---|
32 | ; Structures and Typedefs
|
---|
33 | ;
|
---|
34 | RXSTRING STRUC
|
---|
35 | cb dd ?
|
---|
36 | pach dd ?
|
---|
37 | RXSTRING ENDS
|
---|
38 |
|
---|
39 |
|
---|
40 |
|
---|
41 | DATA32 segment dword public 'DATA' use32
|
---|
42 | ;
|
---|
43 | ; Global Variables
|
---|
44 | ;
|
---|
45 | ifdef DEBUG
|
---|
46 | ;Debug stuff
|
---|
47 | szMsgDebug1 db "Debug1",13,10,0
|
---|
48 | szMsgDebug2 db "Debug2",13,10,0
|
---|
49 | szMsgDebug3 db "Debug3",13,10,0
|
---|
50 | endif
|
---|
51 |
|
---|
52 | ;Error messages.
|
---|
53 | szMsgScriptnameTooLong db "Fatal error: The scriptname is too long.",13,10,0
|
---|
54 | szMsgArgumentsTooLong db "Fatal error: The arguments are too long.",13,10,0
|
---|
55 | szMsgRexxStartFailed db "Fatal error: RexxStart failed.",13,10,0
|
---|
56 |
|
---|
57 | ;Rexx argument string
|
---|
58 | rxstrArgs RXSTRING <0, offset szArgs>
|
---|
59 |
|
---|
60 | ;Command env. name - RexxStart param - dont't know what it is used for...
|
---|
61 | szEnv db "hmm", 0
|
---|
62 |
|
---|
63 | ;Some uninitialized buffers
|
---|
64 | szScriptname db 260d dup (?)
|
---|
65 | szArgs db MAX_ARG_LENGTH dup (?)
|
---|
66 |
|
---|
67 | DATA32 ends
|
---|
68 |
|
---|
69 |
|
---|
70 |
|
---|
71 | CODE32 segment dword public 'CODE' use32
|
---|
72 |
|
---|
73 | ;;
|
---|
74 | ; Exe Entry Point.
|
---|
75 | ; @returns
|
---|
76 | ; @param eax = eax = ebx = ecx = esi = edi = ebp = 0
|
---|
77 | ; @param [esp + 00h] Return address. (32-bit flat)
|
---|
78 | ; @param [esp + 04h] Module handle for program module.
|
---|
79 | ; @param [esp + 08h] Reserved
|
---|
80 | ; @param [esp + 0ch] Environment data object address.
|
---|
81 | ; @param [esp + 10h] Command line linear address in environemnt data object.
|
---|
82 | ; @uses
|
---|
83 | ; @equiv
|
---|
84 | ; @time
|
---|
85 | ; @sketch
|
---|
86 | ; @status
|
---|
87 | ; @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
|
---|
88 | ; @remark
|
---|
89 | main PROC NEAR
|
---|
90 | hModule EQU [ebp + 08h]
|
---|
91 | pEnvironment EQU [ebp + 10h]
|
---|
92 | pCommandline EQU [ebp + 14h]
|
---|
93 | LOCAL sRexxRc:word
|
---|
94 | LOCAL cbActual:dword
|
---|
95 |
|
---|
96 | ;
|
---|
97 | ; Find the arguments
|
---|
98 | ;
|
---|
99 | mov eax, pCommandline
|
---|
100 | call strlen
|
---|
101 | add eax, pCommandline
|
---|
102 |
|
---|
103 | ;
|
---|
104 | ; The script name is the first argument to this program
|
---|
105 | ; The script arguments are following, so we'll have to find them..
|
---|
106 | ;
|
---|
107 |
|
---|
108 |
|
---|
109 | ;
|
---|
110 | ; Copy the script name.
|
---|
111 | ;
|
---|
112 | mov ecx, 260 ; Max length.
|
---|
113 | xchg esi, eax ; esi <- Pointer to the arguments (script name) (-1).
|
---|
114 | mov edi, offset szScriptname ; edi <- Target string buffer for the script name.
|
---|
115 |
|
---|
116 | mov ah, ' ' ; terminator is ' ' or '\0'
|
---|
117 | skiploop1: ; skip spaces
|
---|
118 | inc esi ; next char (initially at terminator of exe name).
|
---|
119 | mov al, byte ptr [esi] ; Get first char to determin terminator type.
|
---|
120 | cmp al, ah
|
---|
121 | jz skiploop1
|
---|
122 |
|
---|
123 | cmp al, '"' ; if not '"' then goto copy loop.
|
---|
124 | jne loop1
|
---|
125 |
|
---|
126 | mov al, '"' ; terminator is '"' or '\0'
|
---|
127 | inc eax ; skip '"'.
|
---|
128 |
|
---|
129 |
|
---|
130 | loop1:
|
---|
131 | or al, al ; zero terminator?
|
---|
132 | jz endloop1
|
---|
133 |
|
---|
134 | cmp al, ah ; the other terminator?
|
---|
135 | jz endloop1
|
---|
136 |
|
---|
137 | stosb ; copy the byte
|
---|
138 |
|
---|
139 |
|
---|
140 | ; next char
|
---|
141 | inc esi ; next
|
---|
142 | dec ecx ; check that we haven't reached the max length.
|
---|
143 | jz Scriptname_Too_Long
|
---|
144 |
|
---|
145 | mov al, byte ptr [esi] ; read (next) byte
|
---|
146 | jmp loop1
|
---|
147 |
|
---|
148 | endloop1:
|
---|
149 | mov byte ptr [edi], 0 ; terminate scriptname.
|
---|
150 |
|
---|
151 | ; more arguments?
|
---|
152 | or al, al ; stopped at null terminator, then no more args.
|
---|
153 | jz callrexx
|
---|
154 | inc esi ; skip terminator.
|
---|
155 |
|
---|
156 | ;
|
---|
157 | ; skip spaces between the scriptname and the first argument.
|
---|
158 | loop2:
|
---|
159 | mov al, byte ptr [esi]
|
---|
160 | cmp al, ' '
|
---|
161 | jne endloop2
|
---|
162 | inc esi
|
---|
163 | jmp loop2
|
---|
164 | endloop2:
|
---|
165 |
|
---|
166 | ;
|
---|
167 | ; Copy arguments, we'll copy till '\0'
|
---|
168 | ;
|
---|
169 | mov eax, esi
|
---|
170 | call strlen ; get argument length
|
---|
171 | mov ecx, eax ; ecx <- number of bytes to copy (argument length).
|
---|
172 | mov rxstrArgs.cb, ecx ; Set length of rexx argument string.
|
---|
173 | cmp ecx, MAX_ARG_LENGTH
|
---|
174 | jae Arguments_Too_Long ; Overflow detected.
|
---|
175 | mov edi, offset szArgs ; edi <- Target argument buffer.
|
---|
176 | repnz movsb ; memcpy(edi, esi, ecx);
|
---|
177 | ; Not sure if it copies the '\0', but that
|
---|
178 | ; don't matter while the memory is initialized
|
---|
179 | ; to zero by the OS!
|
---|
180 |
|
---|
181 | callrexx:
|
---|
182 | ; init return string.
|
---|
183 | xor ebx, ebx ; ebx <- 0
|
---|
184 |
|
---|
185 | push ebx ; NULL - Rexx program return string.
|
---|
186 | lea eax, sRexxRc
|
---|
187 | push eax ; Rexx program return code.
|
---|
188 | push ebx ; NULL - EXIT (FIXME?)
|
---|
189 | push ebx ; RXCOMMAND (0) - Program called as Command.
|
---|
190 | push offset szEnv ; Command env. name. What is this????
|
---|
191 | push ebx ; NULL - Pointer to INSTORE? Not used.
|
---|
192 | push offset szScriptname ; Name of REXX script.
|
---|
193 | push offset rxstrArgs ; Pointer to argument array (rexx strings) - 1 element.
|
---|
194 | push 1 ; Number of arguments - one.
|
---|
195 | call RexxStart
|
---|
196 | sub esp, DWORD * 9
|
---|
197 |
|
---|
198 | ;Check return value from RexxStart
|
---|
199 | or eax, eax
|
---|
200 | jnz RexxStartFailed
|
---|
201 |
|
---|
202 | ;
|
---|
203 | ; return rexx error code.
|
---|
204 | ;
|
---|
205 | mov ax, sRexxRc
|
---|
206 | ret
|
---|
207 |
|
---|
208 |
|
---|
209 | ;
|
---|
210 | ; errors
|
---|
211 | ;
|
---|
212 | Scriptname_Too_Long:
|
---|
213 | mov eax, offset szMsgScriptnameTooLong
|
---|
214 | jmp PrintError
|
---|
215 |
|
---|
216 | Arguments_Too_Long:
|
---|
217 | mov eax, offset szMsgArgumentsTooLong
|
---|
218 | jmp PrintError
|
---|
219 |
|
---|
220 | RexxStartFailed:
|
---|
221 | mov eax, offset szMsgRexxStartFailed
|
---|
222 | jmp PrintError
|
---|
223 |
|
---|
224 | PrintError:
|
---|
225 | lea ebx, cbActual
|
---|
226 | push ebx ; cbActual - last arg for DosWrite
|
---|
227 | mov ebx, eax ; ebx <- string pointer
|
---|
228 | call strlen
|
---|
229 | push eax ; Bytes to write
|
---|
230 | push ebx ; Pointer to string.
|
---|
231 | push 1 ; stderr
|
---|
232 | call DosWrite
|
---|
233 | sub esp, DWORD * 4 ; clean stack.
|
---|
234 |
|
---|
235 | mov eax, -10002
|
---|
236 | ret
|
---|
237 | main ENDP
|
---|
238 |
|
---|
239 | ;;
|
---|
240 | ; String length function.
|
---|
241 | ; @cproto int _Optlink strlen(const char *)
|
---|
242 | ; @returns eax = string length.
|
---|
243 | ; @param eax pointer to string.
|
---|
244 | ; @uses ecx, edx
|
---|
245 | strlen PROC NEAR
|
---|
246 | push edi
|
---|
247 |
|
---|
248 | xor ecx, ecx
|
---|
249 | dec ecx ; ecx <- 0ffffffffh
|
---|
250 | mov edi, eax ; esi <- string pointer
|
---|
251 | xor eax, eax ; scan until null terminator is found.
|
---|
252 |
|
---|
253 | repnz scasb ; the actual scan.
|
---|
254 | neg ecx ; ecx is ffffffffh - string length
|
---|
255 | ; negate it to get the string length.
|
---|
256 | mov eax, ecx ; mov string length into eax (return value)
|
---|
257 | sub eax, 2 ; addjust it.
|
---|
258 |
|
---|
259 | pop edi
|
---|
260 | ret
|
---|
261 | strlen ENDP
|
---|
262 |
|
---|
263 |
|
---|
264 | ifdef DEBUG
|
---|
265 | ;;
|
---|
266 | ; Write debug string to stdout.
|
---|
267 | ;
|
---|
268 | ; @param eax Pointer to string.
|
---|
269 | ; @uses
|
---|
270 | ; @equiv
|
---|
271 | ; @time
|
---|
272 | ; @sketch
|
---|
273 | ; @status
|
---|
274 | ; @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
|
---|
275 | ; @remark
|
---|
276 | debugwrite PROC NEAR
|
---|
277 | LOCAL cbActual:dword
|
---|
278 | push ebx
|
---|
279 | push esi
|
---|
280 | push edi
|
---|
281 |
|
---|
282 | ;
|
---|
283 | ; Write the arguments to stdout.
|
---|
284 | ;
|
---|
285 | push ebx
|
---|
286 | lea ebx, cbActual
|
---|
287 | push ebx ; cbActual - last arg for DosWrite
|
---|
288 | mov ebx, eax
|
---|
289 | call strlen
|
---|
290 | push eax ; Bytes to write
|
---|
291 | push ebx ; Pointer to string.
|
---|
292 | push 1 ; stdout
|
---|
293 | call DosWrite
|
---|
294 | sub esp, DWORD * 4 ; clean stack.
|
---|
295 |
|
---|
296 | pop edi
|
---|
297 | pop esi
|
---|
298 | pop ebx
|
---|
299 | ret
|
---|
300 | debugwrite ENDP
|
---|
301 |
|
---|
302 | endif
|
---|
303 |
|
---|
304 |
|
---|
305 | CODE32 ENDS
|
---|
306 |
|
---|
307 | END main
|
---|