1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; UrForth level
1: self
-hosting
32-bit Forth compiler
3 ;; Copyright
(C
) 2020 Ketmar Dark
// Invisible Vector
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 code: (URFORTH-DEBUGGER-CODEBLOCK)
11 urfdebug_active_flag
: dd
0
12 urfdebug_input_fd
: dd
0 ;; default input is stdin
14 urfdebug_dump_ddepth
: dd
7 ;; default depth of the data stack dump
-1
15 urfdebug_dump_rdepth
: dd
7 ;; default depth of the data stack dump
-1
17 urfdebug_bp_rdepth
: dd
-1 ;; otherwise activate when
return stack depth reaches this
18 urfdebug_sobp_address
: dd
-1 ;; breakpoint address
(at which we should restore dword
)
19 ;;urfdebug_sobp_value
: dd
0 ;; breakpoint address
(at which we should restore dword
)
22 URFORTH_DEBUG_MAX_BPS equ
16
25 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27 urfdebug_tib_size equ $
-urfdebug_tib
29 urfdebug_saved_tio
: rb
80 ;; actually
, 60, but who cares
31 dd
0x00002102 ;; c_iflag
32 dd
0x00000005 ;; c_oflag
33 dd
0x000008B0 ;; c_cflag
34 dd
0x00008A3B ;; c_lflag
36 db
0x03,0x1C,0x7F,0x15,0x04,0x00,0x01,0x00,0x11,0x13,0x1A,0x00,0x12,0x0F,0x17,0x16 ;; c_cc
37 db
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;; c_cc
43 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46 ;; EAX
: buffer
(60 bytes
)
48 ;; EAX
: error
-or
-0, flags dead
, others unchanged
49 urfdebug_set_tio_mode
:
56 ld ecx
,0x5404 ;; TCSETSF
(TCSAFLUSH
)
64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67 ;; EAX
: buffer
(60 bytes
)
69 ;; EAX
: error
-or
-0, flags dead
, others unchanged
70 urfdebug_get_tio_mode
:
77 ld ecx
,0x5401 ;; TCGETS
85 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
88 ld dword
[urfdebug_active_flag
],1
89 ;;ld dword
[urforth_next_ptr
],urfdebug_next
90 ;; put
"jmp near urfdebug_next" there
91 ld byte
[urforth_next
],0xe9 ;; jmp near imm
93 sub eax
,urforth_next
+5
94 ld
[urforth_next
+1],eax
97 urfdebug_deactivate_it
:
98 ld dword
[urfdebug_active_flag
],0
99 ;;ld dword
[urforth_next_ptr
],urforth_next_normal
100 ;; put
0xff 0xe0 there
(jmp eax
)
102 ld dword
[urforth_next
],eax
106 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
107 ;; print asciiz string from EAX
109 ;; EAX
: start address
111 ;; EAX
: right after terminating zero
112 ;; all other registers are preserved
(excluding flags
)
114 urfdebug_emit_str_asciiz_eax
:
121 call urfsegfault_emit_al
129 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
131 ;; all registers are preserved
, excluding EAX
132 ;; on EOF
, EAX is
0, and zero flag is set
133 ;; on success
, EAX is
!0, and zero flag is reset
136 save_all_regs_no_eax_f
138 push eax
;; we will
read char here
140 mov ebx
,[urfdebug_input_fd
]
141 mov ecx
,esp
;; address
144 ;; check number of
read chars
148 jr z
,urfdebug_getch_eof
149 and eax
,0xff ;; safety
, and zero check
150 jr nz
,urfdebug_getch_ok
152 or al
,al
;; reset zero flag
154 restore_all_regs_no_eax_f
157 xor eax
,eax
;; also sets zero flag
161 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
162 ;; read input line into urfdebug_tib
165 ;; ECX
: line length
, without CR
166 ;; zero flag
: set on EOF
(never set on non
-empty line
)
167 ;; other flags are dead
168 ;; other registers are preserved
169 ;; always terminates input string with
0
174 mov ecx
,urfdebug_tib_size
-1
175 urfdebug_getline_loop
:
177 ;; ECX
: bytes left in destination
(excluding room
for terminating
0)
179 jr z
,urfdebug_getline_eof
181 jr z
,urfdebug_getline_done
183 jr z
,urfdebug_getline_done
185 loop urfdebug_getline_loop
186 ;; either EOL
, or
end of input buffer
188 urfdebug_getline_done:
189 ;; store terminating 0
192 ;; calculate line length
193 mov eax,urfdebug_tib_size-1
199 urfdebug_getline_exit:
204 urfdebug_getline_eof:
205 ;; eof: check for empty line
207 jr nz,urfdebug_getline_done
208 ;; empty line and eof: real eof
209 ;; store terminating zero
212 ;; return 0 length, and zero flag set
214 jr urfdebug_getline_exit
217 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
221 ;; ESI: input buffer start
223 ;; ESI: pointer to non-blank or zero char
224 ;; EAX: non-blank char
225 ;; ZERO SET if ESI points to zero char (i.e. on EOL)
226 ;; all other registers are preserved, except flags
228 urfdebug_skip_blanks:
231 jr z,urfdebug_skip_blanks_stop
233 jr c,urfdebug_skip_blanks
234 urfdebug_skip_blanks_stop:
240 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
241 ;; convert AL to digit in hex
242 ;; sets carry on error (and AL is undefined)
243 ;; all other registers are preserved, except flags
263 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
267 ;; ESI: input buffer start (blanks must be skipped!)
269 ;; ESI: pointer to non-blank or zero char
270 ;; EAX: parsed number
271 ;; CARRY SET if not a number (in this case ESI is not modified, and EAX is garbage)
272 ;; all other registers are preserved, except flags
274 urfdebug_parse_number:
275 push esi ;; we may need to restore it
277 push eax ;; negate flag
278 push eax ;; number base
279 push eax ;; number accumulator
281 ;; [esp] -- accumulator
283 ;; [esp+8] -- negate flag
286 jp z,urfdebug_parse_number_error
288 ;; check for negative/positive
293 jr urfdebug_parse_number_check_prefixes
300 urfdebug_parse_number_check_prefixes:
303 ;; check for possible sigils
320 ;; check for possible C-like prefix
322 jp nz,urfdebug_parse_number_no_c_prefix
327 jp urfdebug_parse_number_no_c_prefix
333 jr urfdebug_parse_number_no_c_prefix
339 jr urfdebug_parse_number_no_c_prefix
345 jr urfdebug_parse_number_no_c_prefix
351 jr urfdebug_parse_number_no_c_prefix
357 jr urfdebug_parse_number_no_c_prefix
363 jr urfdebug_parse_number_no_c_prefix
369 jr urfdebug_parse_number_no_c_prefix
372 urfdebug_parse_number_no_c_prefix:
373 ;; first must be a digit
375 call urfdebug_digit_al
376 jr c,urfdebug_parse_number_error
378 jr nc,urfdebug_parse_number_error
380 urfdebug_parse_number_loop:
383 jr c,urfdebug_parse_number_complete
385 jr z,urfdebug_parse_number_loop
386 call urfdebug_digit_al
387 jr c,urfdebug_parse_number_error
389 jr nc,urfdebug_parse_number_error
395 movzx ecx,byte [esp+4+4+4+4]
404 jr urfdebug_parse_number_loop
406 urfdebug_parse_number_complete:
407 dec esi ;; back to the last non-number char
408 call urfdebug_skip_blanks
415 or eax,eax ;; reset carry
418 urfdebug_parse_number_error:
425 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
429 ;; ESI: input buffer start
432 ;; ESI: next input buffer token (blanks skipped)
433 ;; EAX: command handler address
439 ;; all registers are preserved, except flags
441 urfdebug_find_command:
442 push esi ;; in case we'll need
to restore it
443 call urfdebug_skip_blanks
444 jr z
,urfdebug_find_command_eol
445 ;; save two reginster we will use as working set
448 ;; load table address
449 mov edi
,urfdebug_command_table
450 urfdebug_find_command_loop
:
452 ;; EDI
: commant table
453 ;; EAX
,ECX
: scratchpad
454 mov eax
,[edi
] ;; handler address
456 jr z
,urfdebug_find_command_not_found
457 ;; EAX contains handler address
461 add edi
,4 ;; skip handler address
462 ;; save esi
, because we will need
to restore it on failure
464 ;; compare until different
, or until table name terminates
465 urfdebug_find_command_cmpname_loop
:
466 movzx eax
,byte
[esi
] ;; input byte
467 ;; if space
, convert
to 0, so we can compare it with name terminator
469 jr nc
,urfdebug_find_command_cmpname_loop_good_al
471 urfdebug_find_command_cmpname_loop_good_al
:
472 cmp al
,[edi
] ;; compare with name byte
473 jr nz
,urfdebug_find_command_cmpname_loop_failed
474 ;; the bytes are the same
, advance pointers
477 ;; check
for end-of
-word
479 jr nz
,urfdebug_find_command_cmpname_loop
480 ;; command name matches
481 ;; ESI
: after the command text
, and the last space
/0
482 ;; EDI
: after the command name in the table
, and the trailing
0
483 ;; on stack
: original ESI
, handler address
484 dec esi
;; backup one char in case it was
0
485 call urfdebug_skip_blanks
486 pop eax
;; drop original ESI
, we don
't need it anymore
487 pop eax ;; this is our return result
488 ;; restore trashed registers
491 add esp,4 ;; ignore saved oritinal ESI
494 urfdebug_find_command_cmpname_loop_failed:
495 ;; ESI: in the command text
496 ;; EDI: in the name text
497 ;; on stack: original ESI, handler address
498 pop esi ;; restore original ESI
499 pop eax ;; we don't need it
, so this is just
"drop"
500 ;; skip the rest of the name
501 urfdebug_find_command_cmpname_loop_failed_skip
:
505 jr nz
,urfdebug_find_command_cmpname_loop_failed_skip
512 jr urfdebug_find_command_loop
514 urfdebug_find_command_not_found
:
517 urfdebug_find_command_eol
:
523 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
524 $
if URFORTH_EXTRA_STACK_CHECKS
525 ;; flags and EAX are already saved
; all others should be preserved
526 urfdebug_stack_check
:
527 ld eax
,ts
:[ua_ofs_sp0
]
532 ld dword
[urfdebug_active_flag
],1
538 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
539 ;; main debugger entry point
540 ;; all registers are preserved
, including flags
543 ;; save eax and flags
, check
for early exit
545 cmp dword
[urfdebug_active_flag
],-1
548 $
if URFORTH_EXTRA_STACK_CHECKS
549 call urfdebug_stack_check
551 cmp dword
[urfdebug_active_flag
],0
552 jr nz
,urfdebug_active
553 ;; special flag
, means
"no breakpoint checks"
554 ;; check
for breakpoints
555 ld eax
,[urfdebug_sobp_address
]
556 add eax
,4 ;; compensate
for loaded dword
559 ;; check
for rdepth breakpoint
560 cp ERP
,[urfdebug_bp_rdepth
]
562 ;; no breakpoints
, get out
569 ;; debugger is active here
571 ;; save other registers
572 pop eax
;; original eax
573 mov
[urfsegfault_reg_eax
],eax
575 mov
[urfsegfault_reg_flags
],eax
576 mov
[urfsegfault_reg_ebx
],ebx
577 mov
[urfsegfault_reg_ebx
],ebx
578 mov
[urfsegfault_reg_ecx
],ecx
579 mov
[urfsegfault_reg_edx
],edx
580 mov
[urfsegfault_reg_esi
],esi
581 mov
[urfsegfault_reg_edi
],edi
582 mov
[urfsegfault_reg_ebp
],ebp
584 ;; get
return address
587 mov
[urfsegfault_dbg_retaddr
],eax
589 ;; now save stack pointer
590 mov
[urfsegfault_reg_esp
],esp
591 ;; just in case
, ensure that the direction flag is clear
(autoincrement
)
594 ;; switch to our own stack
595 ld eax
,[urfsegfault_stack_bottom
]
598 ;; save terminal mode
599 ld eax
,urfdebug_saved_tio
600 call urfdebug_get_tio_mode
601 ;; set
"cooked" terminal mode
602 ld eax
,urfdebug_cooked_tio
603 call urfdebug_set_tio_mode
606 ;;ld dword
[urfdebug_active_flag
],1
607 call urfdebug_activate_it
608 ;; reset rdepth breakpoint
609 ld dword
[urfdebug_bp_rdepth
],-1
610 ;; reset step
-over breakpoint
611 ld dword
[urfdebug_sobp_address
],-1
613 ;; main debugger loop
615 ;; print debugger prompt
, data stack depth
, return stack depth
616 ld eax
,[urfsegfault_reg_esp
]
617 call urfsegfault_emit_hex_eax
619 urfsegfault_printstr
"UDBG:D("
621 ;; print data stack depth
622 ld eax
,ts
:[ua_ofs_sp0
]
623 sub eax
,[urfsegfault_reg_esp
]
624 sar eax
,2 ;; divide by cell
625 urfsegfault_printdec eax
627 ;; print
return stack depth
628 urfsegfault_printstr
"):R("
629 ld eax
,ts
:[ua_ofs_rp0
]
630 sub eax
,[urfsegfault_reg_ebp
]
631 sar eax
,2 ;; divide by cell
632 urfsegfault_printdec eax
634 ;; print the word we
're currently executing
635 urfsegfault_printstr "):"
636 mov eax,[urfsegfault_reg_esi]
637 sub eax,4 ;; because we just loaded it
638 call urfsegfault_find_by_addr
639 ;; print line number if we know it
642 ld eax,[urfsegfault_reg_esi]
643 sub eax,4 ;; because we just loaded it
644 call urfsegfault_find_pc_line_nfa
647 urfsegfault_printstr "{"
648 call urfsegfault_emit_dec_eax
650 call urfsegfault_nfa_write_fname
651 urfsegfault_printstr "}"
654 ;; done printing line
655 call urfsegfault_nfaprint
657 ;; print the word we'll jump into
658 urfsegfault_printstr
" -> "
659 mov eax
,[urfsegfault_reg_eax
]
660 call urfsegfault_find_by_addr
662 call urfsegfault_nfaprint
664 ld esi
,[urfsegfault_reg_esi
]
665 call urfsegfault_nfa_print_arg
668 urfsegfault_printstr
" | "
669 mov eax
,[urfsegfault_reg_esi
]
670 sub eax
,4 ;; because we just loaded it
671 call urfsegfault_emit_hex_eax
674 urfsegfault_printstr
" -> "
675 mov eax
,[urfsegfault_reg_eax
]
676 call urfsegfault_emit_hex_eax
678 ;; print the rest of the prompt
679 urfsegfault_printstr
" |>"
682 call urfdebug_getline
683 ;; ECX is length
; ZERO SET on EOF
685 jr z
,urfdebug_deactivate
686 ;; continue on empty command
691 call urfdebug_find_command
692 jr z
,urfdebug_unknown_command
694 ;;call uefdebug_call_eax
698 urfdebug_unknown_command
:
699 ;; for now
, simply echo the command
704 jr z
,urfdebug_echo_loop_done
705 call urfsegfault_emit_al
706 jr urfdebug_echo_loop
707 urfdebug_echo_loop_done
:
708 ;;urfsegfault_emit
'|'
710 urfsegfault_printstrnl
"? what?"
715 urfdebug_deactivate_nocr
:
716 ;;mov dword
[urfdebug_active_flag
],0
717 call urfdebug_deactivate_it
720 ;; restore terminal mode
721 ld eax
,urfdebug_saved_tio
722 call urfdebug_set_tio_mode
725 mov ebx
,[urfsegfault_reg_ebx
]
726 mov ecx
,[urfsegfault_reg_ecx
]
727 mov edx
,[urfsegfault_reg_edx
]
728 mov esi
,[urfsegfault_reg_esi
]
729 mov edi
,[urfsegfault_reg_edi
]
730 mov ebp
,[urfsegfault_reg_ebp
]
732 mov eax
,[urfsegfault_reg_flags
]
736 mov esp
,[urfsegfault_reg_esp
]
738 ;; push
return address
739 mov eax
,[urfsegfault_dbg_retaddr
]
742 ;; restore eax
, and exit
743 mov eax
,[urfsegfault_reg_eax
]
748 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
750 ;; handler will be called with ESI pointing
to unparsed arguments
(blanks skipped
)
752 urfdebug_command_table
:
753 dd urfdebug_cmd_printdstack
755 db
"dump data stack",0
756 dd urfdebug_cmd_printrstack
758 db
"dump return stack",0
759 dd urfdebug_cmd_step_out
761 db
"continue until current word returned",0
762 dd urfdebug_cmd_step_over
764 db
"step over the current word",0
765 dd urfdebug_cmd_deactivate
767 db
"deactivate debugger",0
771 db
"drop number from data stack",0
774 db
"swap numbers at data stack",0
777 db
"push number at data stack",0
779 dd urfdebug_cmd_ddepth
781 db
"set data stack dump depth",0
782 dd urfdebug_cmd_rdepth
784 db
"set return stack dump depth",0
788 db
"decompile forth word",0
790 dd urfdebug_cmd_fcall
792 db
"call forth word",0
796 db
"show this help",0
800 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
801 ;; drop value from data stack
804 ld eax
,ts
:[ua_ofs_sp0
]
805 sub eax
,[urfsegfault_reg_esp
]
808 urfsegfault_printstrnl
"stack underflowed"
813 ld edi
,[urfsegfault_reg_esp
]
816 ld
[urfsegfault_reg_ecx
],eax
818 ld
[urfsegfault_reg_esp
],edi
822 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
823 ;; swap values on data stack
826 ld eax
,ts
:[ua_ofs_sp0
]
827 sub eax
,[urfsegfault_reg_esp
]
830 urfsegfault_printstrnl
"stack underflowed"
835 urfsegfault_printstrnl
"stack should have at least two values"
839 ld edi
,[urfsegfault_reg_esp
]
841 ld ecx
,[urfsegfault_reg_ecx
]
843 ld
[urfsegfault_reg_ecx
],eax
847 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
848 ;; push value on data stack
851 ld eax
,ts
:[ua_ofs_sp0
]
852 sub eax
,[urfsegfault_reg_esp
]
855 urfsegfault_printstrnl
"stack underflowed"
858 urfdebug_cmd_push_parse_loop
:
859 call urfdebug_skip_blanks
861 call urfdebug_parse_number
863 urfsegfault_printstrnl
"not a number!"
866 ld edi
,[urfsegfault_reg_esp
]
867 ld ecx
,[urfsegfault_reg_ecx
]
870 ld
[urfsegfault_reg_ecx
],eax
871 ld
[urfsegfault_reg_esp
],edi
872 jr urfdebug_cmd_push_parse_loop
875 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
879 urfsegfault_printstrnl
"------ HELP ------"
880 ld esi
,urfdebug_command_table
881 urfdebug_cmd_help_loop
:
886 urfsegfault_printstr
" "
887 call urfdebug_emit_str_asciiz_eax
889 call urfdebug_emit_str_asciiz_eax
892 jr urfdebug_cmd_help_loop
895 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
896 ;; deactivate until current word exited
898 urfdebug_cmd_step_out
:
899 ;; check
return stack depth
900 ld eax
,ts
:[ua_ofs_rp0
]
901 cmp eax
,[urfsegfault_reg_ebp
]
902 jr z
,urfdebug_cmd_step_out_cannot
903 jr c
,urfdebug_cmd_step_out_cannot
904 ld eax
,[urfsegfault_reg_ebp
]
905 add eax
,4 ;; one level up
906 ld
[urfdebug_bp_rdepth
],eax
907 ;; done
, deactivate debugger
908 ;;jp urfdebug_deactivate_nocr
909 ld dword
[urfdebug_active_flag
],0
911 urfdebug_cmd_step_out_cannot
:
912 urfsegfault_printstrnl
"cannot step out, return stack is empty!"
916 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
917 ;; perform
"step over"
919 urfdebug_cmd_step_over
:
920 ;; sanity check
, just in case
921 cp dword
[urfdebug_sobp_address
],-1
922 jr nz
,urfdebug_cmd_step_over_error
923 ;; check
if the next address is still in the current word
924 ;; that next address is actually in EIP
925 mov eax
,[urfsegfault_reg_esi
]
926 call urfsegfault_find_by_addr
927 jp z
,urfdebug_cmd_step_over_bad_addr
929 mov eax
,[urfsegfault_reg_esi
]
930 sub eax
,4 ;; current instruction
931 call urfsegfault_find_by_addr
932 jp z
,urfdebug_cmd_step_over_bad_addr
934 jp nz
,urfdebug_cmd_step_over_bad_addr
936 mov eax
,[urfsegfault_reg_eax
]
937 call urfsegfault_find_by_addr
938 jp z
,urfdebug_cmd_step_over_bad_addr
940 movzx eax
,word
[edi
+2]
941 test eax
,FLAG_NORETURN
942 jp nz
,urfdebug_cmd_step_over_noreturn
943 ;; load argument type
944 movzx eax
,byte
[edi
+1]
945 ld esi
,[urfsegfault_reg_esi
]
946 ;; check instruction argument type
948 jr z
,urfdebug_cmd_step_over_branch
950 call urfsegfault_nfa_skip_arg_type_in_eax
951 urfdebug_cmd_step_over_set_sobp
:
952 ;; setup debugger activation address
953 ld dword
[urfdebug_sobp_address
],esi
954 ;; done
, deactivate debugger
955 ;;jp urfdebug_deactivate_nocr
956 ld dword
[urfdebug_active_flag
],0
958 urfdebug_cmd_step_over_error
:
959 urfsegfault_printstrnl
"step-over breakpoint already set for some strange reason!"
961 urfdebug_cmd_step_over_bad_addr
:
962 ;;urfsegfault_printstrnl
"cannot step-over outside of the word!"
964 ;; just
continue into it
966 urfdebug_cmd_step_over_branch
:
967 ;;urfsegfault_printstrnl
"cannot step over branches yet!"
969 ;; just
continue into it
971 urfdebug_cmd_step_over_noreturn
:
972 ;;urfsegfault_printstrnl
"cannot step over NORETURN words!"
974 ;; just
continue into it
978 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
979 ;; print
return stack
981 urfdebug_cmd_printrstack
:
982 push dword
[urfsegfault_dump_rdepth
]
983 ld eax
,[urfdebug_dump_rdepth
]
984 ld
[urfsegfault_dump_rdepth
],eax
985 call urfsegfault_cmd_printrstack
986 pop dword
[urfsegfault_dump_rdepth
]
990 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
993 urfdebug_cmd_printdstack
:
994 push dword
[urfsegfault_dump_ddepth
]
995 ld eax
,[urfdebug_dump_ddepth
]
996 ld
[urfsegfault_dump_ddepth
],eax
997 call urfsegfault_cmd_printdstack
998 pop dword
[urfsegfault_dump_ddepth
]
1002 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1003 ;; deactivate debugger
1005 urfdebug_cmd_deactivate
:
1006 jp urfdebug_deactivate_nocr
1009 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1010 ;; set data stack dump depth
1012 urfdebug_cmd_ddepth
:
1013 call urfdebug_parse_number
1015 urfsegfault_printstrnl
"number expected!"
1020 urfsegfault_printstrnl
"minimum value is 2!"
1025 urfsegfault_printstrnl
"minimum value is 200!"
1029 ld
[urfdebug_dump_ddepth
],eax
1033 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1034 ;; set
return stack dump depth
1036 urfdebug_cmd_rdepth
:
1037 call urfdebug_parse_number
1039 urfsegfault_printstrnl
"number expected!"
1044 urfsegfault_printstrnl
"minimum value is 2!"
1049 urfsegfault_printstrnl
"minimum value is 200!"
1053 ld
[urfdebug_dump_rdepth
],eax
1057 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1058 ;; decompile forth word
1061 ;; find argument length
1063 urfdebug_cmd_see_arglen_loop
:
1066 jr nc
,urfdebug_cmd_see_arglen_loop
1071 urfsegfault_printstrnl
"what word?"
1074 ;; save starting address and length
1079 mov ebp
,[urfsegfault_reg_ebp
]
1086 call urfsegfault_emit_str_ecx_edx_safe
1087 urfsegfault_printstrnl
"? what is it?"
1091 pop edx
;; saved count
1092 pop ecx
;; saved address
1093 call urfsegfault_emit_str_ecx_edx_safe
1094 urfsegfault_printstr
" is "
1096 call urfsegfault_find_by_addr
1099 urfsegfault_printstrnl
"some shit"
1102 ;;ld esi
,eax
;; save cfa
1103 ;;call urfsegfault_cfa2nfa
1104 ld
[urfdebug_cmd_see_nfa
],eax
;; we
'll need it for debug info printing
1105 call urfsegfault_nfaprint
1106 urfsegfault_printstr " at (nfa) 0x"
1107 call urfsegfault_emit_hex_eax
1111 ld eax,[urfsegfault_fba_nfa]
1112 call urfsegfault_nfa2cfa
1116 jp nz,urfdebug_cmd_see_notforth
1119 $if URFORTH_ALIGN_PFA
1125 jp nz,urfdebug_cmd_see_notforth
1126 urfdebug_cmd_see_loop:
1127 cmp esi,[urfsegfault_fba_end]
1128 jr nc,urfdebug_cmd_see_loop_done
1129 ;; print address (and store it on the stack)
1132 call urfsegfault_emit_hex_eax
1133 urfsegfault_printstr ": "
1135 call urfsegfault_cfa2nfa
1136 call urfsegfault_nfaprint
1138 call urfsegfault_nfa_print_arg
1139 ;; print source code line
1142 ld esi,[urfdebug_cmd_see_nfa]
1143 call urfsegfault_find_pc_line_nfa
1147 urfsegfault_printstr 9,"; line #"
1149 call urfsegfault_emit_dec_eax
1154 jr urfdebug_cmd_see_loop
1156 urfdebug_cmd_see_loop_done:
1160 urfdebug_cmd_see_notforth:
1161 urfsegfault_printstrnl "cannot decompile non-Forth words yet."
1164 urfdebug_cmd_see_nfa: dd 0
1167 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1171 ;; find argument length
1172 call urfdebug_skip_blanks
1182 ;;urfsegfault_printstrnl "what word?"
1185 ;; save starting address and length
1190 mov ebp,[urfsegfault_reg_ebp]
1195 ;; try to parse it as a number
1200 call urfdebug_parse_number
1203 ld edi,[urfsegfault_reg_esp]
1204 ld ecx,[urfsegfault_reg_ecx]
1207 ld [urfsegfault_reg_ecx],eax
1208 ld [urfsegfault_reg_esp],edi
1212 jr urfdebug_cmd_fcall
1216 call urfsegfault_emit_str_ecx_edx_safe
1217 urfsegfault_printstrnl "? what is it?"
1221 ;; switch data stacks
1222 ld [urfdebug_cmd_fcall_esp],esp
1223 ld esp,[urfsegfault_reg_esp]
1224 ld TOS,[urfsegfault_reg_ecx]
1226 ld [urfsegfault_reg_ecx],TOS
1227 ld [urfsegfault_reg_esp],esp
1228 ld esp,[urfdebug_cmd_fcall_esp]
1229 ;; skip word and continue
1233 jp urfdebug_cmd_fcall
1235 urfdebug_cmd_fcall_esp: dd 0
1238 (hidden) (codeblock)
1241 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1243 call urfdebug_activate_it
1247 $constant "(JMP-NEXT-ADDR)" urforth_next
1248 $constant "(HAS-DEBUGGER?)" 1
1249 ;;$constant "(NEXT-REF-ADDR)" urforth_next_ptr
1252 $constant "(HAS-DEBUGGER?)" 0
1253 ;; so i can avoid conditional compilation
1255 ;;$constant "(NEXT-REF-ADDR)" 0
1256 $constant "(JMP-NEXT-ADDR)" 0