initial commit: a mess of assembly code
[fmap.git] / x86_64_sse2_x87 / fasm / source / dos / fasmg.asm
blob4ce246cde74c8be8c5b7fe5f027db57c1f44c5a7
2 match ,{
4 include 'macro/struct.inc'
6 } match -,{
7 else
9 include 'selfhost.inc'
11 end match
12 _ equ }
14 include '../version.inc'
16 BUFFER_SIZE = 4000h
17 STACK_SIZE = 4000h
19 format MZ
20 heap 0
21 stack stack_segment:stack_top-stack_bottom
22 entry loader:startup
24 segment loader use16
26 startup:
28 mov ax,1687h
29 int 2Fh
30 or ax,ax ; DPMI installed?
31 jnz short no_dpmi
32 test bl,1 ; 32-bit programs supported?
33 jz short no_dpmi
34 mov word [cs:mode_switch],di
35 mov word [cs:mode_switch+2],es
36 mov bx,si ; allocate memory for DPMI data
37 mov ah,48h
38 int 21h
39 jnc switch_to_protected_mode
40 init_failed:
41 call startup_error
42 db 'DPMI initialization failed.',0Dh,0Ah,0
43 no_dpmi:
44 call startup_error
45 db '32-bit DPMI services are not available.',0Dh,0Ah,0
46 startup_error:
47 pop si
48 push cs
49 pop ds
50 show_message:
51 lodsb
52 test al,al
53 jz message_shown
54 mov dl,al
55 mov ah,2
56 int 21h
57 jmp show_message
58 message_shown:
59 mov ax,4CFFh
60 int 21h
61 switch_to_protected_mode:
62 mov es,ax
63 mov ds,[ds:2Ch]
64 mov ax,1
65 call far [cs:mode_switch] ; switch to protected mode
66 jc init_failed
67 mov cx,1
68 xor ax,ax
69 int 31h ; allocate descriptor for code
70 jc init_failed
71 mov si,ax
72 xor ax,ax
73 int 31h ; allocate descriptor for data
74 jc init_failed
75 mov di,ax
76 mov dx,cs
77 lar cx,dx
78 shr cx,8
79 or cx,0C000h
80 mov bx,si
81 mov ax,9
82 int 31h ; set code descriptor access rights
83 jc init_failed
84 mov dx,ds
85 lar cx,dx
86 shr cx,8
87 or cx,0C000h
88 mov bx,di
89 int 31h ; set data descriptor access rights
90 jc init_failed
91 mov ecx,main
92 shl ecx,4
93 mov dx,cx
94 shr ecx,16
95 mov ax,7
96 int 31h ; set data descriptor base address
97 jc init_failed
98 mov bx,si
99 int 31h ; set code descriptor base address
100 jc init_failed
101 mov cx,0FFFFh
102 mov dx,0FFFFh
103 mov ax,8 ; set segment limit to 4 GB
104 int 31h
105 jc init_failed
106 mov bx,di
107 int 31h
108 jc init_failed
109 mov ax,ds
110 mov ds,di
111 mov [main_selector],di
112 mov [psp_selector],es
113 mov gs,ax ; environment selector in GS
115 mov ss,di
116 mov esp,stack_top
118 mov es,di
119 mov cx,1
120 xor ax,ax
121 int 31h ; allocate descriptor for BIOS data segment
122 jc init_failed
123 mov bx,ax
124 mov ax,gs
125 lar cx,ax
126 shr cx,8
127 mov ax,9
128 int 31h ; set descriptor access rights
129 jc init_failed
130 xor cx,cx
131 mov dx,400h
132 mov ax,7
133 int 31h ; set base address of BIOS data segment
134 jc init_failed
135 xor cx,cx
136 mov dx,0FFh
137 mov ax,8
138 int 31h ; set limit of BIOS data segment
139 jc init_failed
140 mov fs,bx ; BIOS data selector in FS
141 push si
142 push start
143 retf
145 mode_switch dd ?
147 segment main use32
149 start:
151 call system_init
153 call get_arguments
154 mov bl,al
155 cmp [no_logo],0
156 jne logo_ok
157 mov esi,_logo
158 xor ecx,ecx
159 call display_string
160 logo_ok:
161 test bl,bl
162 jnz display_usage_information
164 xor al,al
165 mov ecx,[verbosity_level]
166 jecxz init
167 or al,TRACE_ERROR_STACK
168 dec ecx
169 jz init
170 or al,TRACE_DISPLAY
171 init:
173 call assembly_init
175 mov eax,[fs:6Ch]
176 mov [timer],eax
178 assemble:
179 mov esi,[initial_commands]
180 mov edx,[source_path]
181 call assembly_pass
182 jc assembly_done
184 mov eax,[current_pass]
185 cmp eax,[maximum_number_of_passes]
186 jb assemble
188 call show_display_data
190 mov esi,_error_prefix
191 xor ecx,ecx
192 call display_error_string
193 mov esi,_code_cannot_be_generated
194 xor ecx,ecx
195 call display_error_string
196 mov esi,_message_suffix
197 xor ecx,ecx
198 call display_error_string
200 jmp assembly_failed
202 assembly_done:
204 call show_display_data
206 cmp [first_error],0
207 jne assembly_failed
209 cmp [no_logo],0
210 jne summary_done
211 mov eax,[current_pass]
212 xor edx,edx
213 call itoa
214 call display_string
215 mov esi,_passes
216 cmp [current_pass],1
217 jne display_passes_suffix
218 mov esi,_pass
219 display_passes_suffix:
220 xor ecx,ecx
221 call display_string
222 mov eax,[fs:6Ch]
223 sub eax,[timer]
224 mov ecx,36000
225 mul ecx
226 shrd eax,edx,16
227 shr edx,16
228 mov ecx,10
229 div ecx
230 mov [timer],edx
231 or edx,eax
232 jz display_output_length
233 xor edx,edx
234 call itoa
235 call display_string
236 mov esi,_message_suffix
237 mov ecx,1
238 call display_string
239 mov eax,[timer]
240 xor edx,edx
241 call itoa
242 call display_string
243 mov esi,_seconds
244 xor ecx,ecx
245 call display_string
246 display_output_length:
247 call get_output_length
248 push eax edx
249 call itoa
250 call display_string
251 pop edx eax
252 mov esi,_bytes
253 cmp eax,1
254 jne display_bytes_suffix
255 test edx,edx
256 jnz display_bytes_suffix
257 mov esi,_byte
258 display_bytes_suffix:
259 xor ecx,ecx
260 call display_string
261 mov esi,_new_line
262 xor ecx,ecx
263 call display_string
264 summary_done:
266 mov ebx,[source_path]
267 mov edi,[output_path]
268 call write_output_file
269 jc write_failed
271 call assembly_shutdown
272 call system_shutdown
274 mov ax,4C00h
275 int 21h
277 assembly_failed:
279 call show_errors
281 call assembly_shutdown
282 call system_shutdown
284 mov ax,4C02h
285 int 21h
287 write_failed:
288 mov ebx,_write_failed
289 jmp fatal_error
291 out_of_memory:
292 mov ebx,_out_of_memory
293 jmp fatal_error
295 fatal_error:
297 mov esi,_error_prefix
298 xor ecx,ecx
299 call display_error_string
300 mov esi,ebx
301 xor ecx,ecx
302 call display_error_string
303 mov esi,_message_suffix
304 xor ecx,ecx
305 call display_error_string
307 call assembly_shutdown
308 call system_shutdown
310 mov ax,4C03h
311 int 21h
313 display_usage_information:
315 mov esi,_usage
316 xor ecx,ecx
317 call display_string
319 call system_shutdown
321 mov ax,4C01h
322 int 21h
324 get_arguments:
325 push ds
326 mov ds,[psp_selector]
327 mov esi,81h
328 mov edi,command_line
329 mov ecx,7Fh
330 move_command_line:
331 lodsb
332 cmp al,0Dh
333 je command_line_moved
334 stosb
335 loop move_command_line
336 command_line_moved:
337 pop ds
338 xor eax,eax
339 stosb
340 mov [initial_commands],eax
341 mov [source_path],eax
342 mov [output_path],eax
343 mov [no_logo],al
344 mov [verbosity_level],eax
345 mov [maximum_number_of_passes],100
346 mov [maximum_number_of_errors],1
347 mov [maximum_depth_of_stack],10000
348 mov [maximum_depth_of_stack],10000
349 mov esi,command_line
350 mov edi,parameters
351 get_argument:
352 xor ah,ah
353 read_character:
354 lodsb
355 test al,al
356 jz no_more_arguments
357 cmp al,22h
358 je switch_quote
359 cmp ax,20h
360 je end_argument
361 stosb
362 jmp read_character
363 end_argument:
364 xor al,al
365 stosb
366 find_next_argument:
367 mov al,[esi]
368 test al,al
369 jz no_more_arguments
370 cmp al,20h
371 jne next_argument_found
372 inc esi
373 jmp find_next_argument
374 switch_quote:
375 xor ah,1
376 jmp read_character
377 next_argument_found:
378 cmp al,'-'
379 je get_option
380 cmp al,'/'
381 je get_option
382 cmp [source_path],0
383 je get_source_path
384 cmp [output_path],0
385 je get_output_path
386 error_in_arguments:
387 or al,-1
388 retn
389 get_source_path:
390 mov [source_path],edi
391 jmp get_argument
392 get_output_path:
393 mov [output_path],edi
394 jmp get_argument
395 no_more_arguments:
396 cmp [source_path],0
397 je error_in_arguments
398 xor al,al
399 stosb
400 retn
401 get_option:
402 inc esi
403 lodsb
404 cmp al,'e'
405 je set_errors_limit
406 cmp al,'E'
407 je set_errors_limit
408 cmp al,'i'
409 je insert_initial_command
410 cmp al,'I'
411 je insert_initial_command
412 cmp al,'p'
413 je set_passes_limit
414 cmp al,'P'
415 je set_passes_limit
416 cmp al,'r'
417 je set_recursion_limit
418 cmp al,'R'
419 je set_recursion_limit
420 cmp al,'v'
421 je set_verbose_mode
422 cmp al,'V'
423 je set_verbose_mode
424 cmp al,'n'
425 je set_no_logo
426 cmp al,'N'
427 jne error_in_arguments
428 set_no_logo:
429 or [no_logo],-1
430 mov al,[esi]
431 cmp al,20h
432 je find_next_argument
433 test al,al
434 jnz error_in_arguments
435 jmp find_next_argument
436 set_verbose_mode:
437 call get_option_value
438 jc error_in_arguments
439 cmp edx,2
440 ja error_in_arguments
441 mov [verbosity_level],edx
442 jmp find_next_argument
443 set_errors_limit:
444 call get_option_value
445 jc error_in_arguments
446 test edx,edx
447 jz error_in_arguments
448 mov [maximum_number_of_errors],edx
449 jmp find_next_argument
450 set_recursion_limit:
451 call get_option_value
452 jc error_in_arguments
453 test edx,edx
454 jz error_in_arguments
455 mov [maximum_depth_of_stack],edx
456 jmp find_next_argument
457 set_passes_limit:
458 call get_option_value
459 jc error_in_arguments
460 test edx,edx
461 jz error_in_arguments
462 mov [maximum_number_of_passes],edx
463 jmp find_next_argument
464 get_option_value:
465 xor eax,eax
466 mov edx,eax
467 find_option_value:
468 cmp byte [esi],20h
469 jne get_option_digit
470 inc esi
471 jmp find_option_value
472 get_option_digit:
473 lodsb
474 cmp al,20h
475 je option_value_ok
476 test al,al
477 jz option_value_ok
478 sub al,30h
479 jc invalid_option_value
480 cmp al,9
481 ja invalid_option_value
482 imul edx,10
483 jo invalid_option_value
484 add edx,eax
485 jc invalid_option_value
486 jmp get_option_digit
487 option_value_ok:
488 dec esi
491 invalid_option_value:
494 insert_initial_command:
495 push edi
496 find_command_segment:
497 cmp byte [esi],20h
498 jne command_segment_found
499 inc esi
500 jmp find_command_segment
501 command_segment_found:
502 xor ah,ah
503 cmp byte [esi],22h
504 jne measure_command_segment
505 inc esi
506 inc ah
507 measure_command_segment:
508 mov ebx,esi
509 scan_command_segment:
510 mov ecx,esi
511 mov al,[esi]
512 test al,al
513 jz command_segment_measured
514 cmp ax,20h
515 je command_segment_measured
516 cmp ax,22h
517 je command_segment_measured
518 inc esi
519 cmp al,22h
520 jne scan_command_segment
521 command_segment_measured:
522 sub ecx,ebx
523 mov edi,[initial_commands]
524 lea eax,[ecx+2]
525 test edi,edi
526 jz allocate_initial_commands_buffer
527 mov edx,[initial_commands_length]
528 add edi,edx
529 add eax,edx
530 cmp eax,[initial_commands_maximum_length]
531 ja grow_initial_commands_buffer
532 copy_initial_command:
533 xchg esi,ebx
534 rep movsb
535 mov esi,ebx
536 sub edi,[initial_commands]
537 mov [initial_commands_length],edi
538 mov al,[esi]
539 test al,al
540 jz initial_command_ready
541 cmp al,20h
542 jne command_segment_found
543 initial_command_ready:
544 mov edi,[initial_commands]
545 add edi,[initial_commands_length]
546 mov ax,0Ah
547 stosw
548 inc [initial_commands_length]
549 pop edi
550 jmp find_next_argument
551 allocate_initial_commands_buffer:
552 push ecx
553 mov ecx,eax
554 call malloc
555 mov [initial_commands],eax
556 mov [initial_commands_maximum_length],ecx
557 mov edi,eax
558 pop ecx
559 jmp copy_initial_command
560 grow_initial_commands_buffer:
561 push ecx
562 mov ecx,eax
563 mov eax,[initial_commands]
564 call realloc
565 mov [initial_commands],eax
566 mov [initial_commands_maximum_length],ecx
567 mov edi,eax
568 add edi,[initial_commands_length]
569 pop ecx
570 jmp copy_initial_command
572 include 'system.inc'
574 include '../assembler.inc'
575 include '../symbols.inc'
576 include '../expressions.inc'
577 include '../conditions.inc'
578 include '../floats.inc'
579 include '../directives.inc'
580 include '../calm.inc'
581 include '../errors.inc'
582 include '../map.inc'
583 include '../reader.inc'
584 include '../output.inc'
585 include '../console.inc'
587 _logo db 'flat assembler version g.',VERSION,13,10,0
589 _usage db 'Usage: fasmg source [output]',13,10
590 db 'Optional settings:',13,10
591 db ' -e limit Set the maximum number of displayed errors (default 1)',13,10
592 db ' -p limit Set the maximum allowed number of passes (default 100)',13,10
593 db ' -r limit Set the maximum depth of the stack (default 10000)',13,10
594 db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,10
595 db ' -i command Insert instruction at the beginning of source',13,10
596 db ' -n Do not show logo nor summary',13,10
597 db 0
599 _pass db ' pass, ',0
600 _passes db ' passes, ',0
601 _dot db '.'
602 _seconds db ' seconds, ',0
603 _byte db ' byte.',0
604 _bytes db ' bytes.',0
606 _write_failed db 'failed to write the output file',0
607 _out_of_memory db 'not enough memory to complete the assembly',0
608 _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
610 include '../tables.inc'
611 include '../messages.inc'
613 align 4
615 include '../variables.inc'
617 psp_selector dw ?
618 main_selector dw ?
620 malloc_freelist dd ?
622 source_path dd ?
623 output_path dd ?
624 maximum_number_of_passes dd ?
626 initial_commands dd ?
627 initial_commands_length dd ?
628 initial_commands_maximum_length dd ?
630 timestamp dq ?
632 timer dd ?
633 verbosity_level dd ?
634 no_logo db ?
636 command_line db 80h dup ?
637 parameters db 80h dup ?
639 segment buffer_segment
641 buffer = (buffer_segment-main) shl 4
643 db BUFFER_SIZE dup ?
645 segment stack_segment
647 stack_bottom = (stack_segment-main) shl 4
649 db STACK_SIZE dup ?
651 stack_top = stack_bottom + $