1 Picking up at the error discovered in the last log,
2 we need to figure out what's happening to the string
3 stored at the label 'errmsg'.
4
5 (I keep having to re-learn that GBD needs an '&' before
6 a label for it to be used as an address expression,
7 otherwise it uses the value _at_ that label. Hope I remember
8 it this time after fumbling around for a while...which is
9 not pictured here.)
10
11 The string is correct ("PARSE ERROR: ") when the program starts.
12 (Though it looks like I didn't get the newline escape right
13 in NASM because I have a literal '\n' in my string!"
14
15 Reading symbols from nasmjf...
16 (gdb) info addr errmsg
17 Symbol "errmsg" is at 0x804a315 in a file compiled without debugging.
18 (gdb) x/20c &errmsg
19 0x804a315 <errmsg>: 80 'P' 65 'A' 82 'R' 83 'S' 69 'E' 32 ' ' 69 'E' 82 'R'
20 0x804a31d: 82 'R' 79 'O' 82 'R' 58 ':' 32 ' ' 92 '\\' 110 'n' 0 '\000'
21 0x804a325: 0 '\000' 0 '\000' 0 '\000' 0 '\000'
22
23 I set a watchpoint on the label and run it.
24
25 (gdb) watch (int)errmsg
26 Watchpoint 2: (int)errmsg
27 (gdb) c
28 Continuing.
29 foo
30
31 Watchpoint 2: (int)errmsg
32
33 Old value = 1397899600
34 New value = 1392508928
35 code_INTERPRET () at nasmjf.asm:214
36 214 call _FIND ; Returns %eax = pointer to header or 0 if not found.
37 (gdb)
38
39 Okay, so I guess that means that the line _before_ 214 must
40 be the culprit. Ah, yeah. That looks likely because here's
41 how the memory is reserved:
42
43 interpret_is_lit: db 0 ; 1 means "reading a literal"
44 errmsg: db "PARSE ERROR: "
45
46 And here's the line before 214:
47
48 mov [interpret_is_lit], eax ; 0 means not a literal number (yet)
49
50 Yup, that sure makes sense! We reserved a byte for the
51 interpret_is_lit flag, but eax is a full word (4 bytes),
52 so the flag is getting set _and_ the remaining three
53 bytes clobber the string in errmsg. It's things like this that
54 make a person appreciate the safety features of higher
55 level languages.
56
57 Angway, the data size was "int" in the JonesForth GAS original.
58 So mine should be 'w' for word:
59
60 interpret_is_lit: dw 0 ; 1 means "reading a literal"
61
62 Let's try it:
63
64 (gdb) file nasmjf
65 Reading symbols from nasmjf...
66 (gdb) break 271
67 Note: breakpoints 3, 4 and 5 also set at pc 0x80490ba.
68 Breakpoint 6 at 0x80490ba: file nasmjf.asm, line 271.
69 (gdb) r
70 Starting program: /home/dave/nasmjf/nasmjf
71 foo
72
73 Breakpoint 3, code_INTERPRET.parse_error () at nasmjf.asm:271
74 271 int 80h
75 PARSE ERROR:
76
77 Yay, that's restored the PARSE ERROR string.
78 Unfortunately, it still ends in a segfault.
79 Oops! Both the errmsgnl and __NR_write labels
80 should be the addresses, not the values at the
81 addresses at lines 284 and 286.
82
83 273 mov [currkey],ecx ; the error occurred just before currkey position
84 274 mov edx,ecx
85 275 sub edx,buffer ; edx = currkey - buffer (length in buffer before currkey)
86 276 cmp edx,40 ; if > 40, then print only 40 characters
87 277 jle .print_error
88 code_INTERPRET.print_error () at nasmjf.asm:280
89 280 sub ecx,edx ; ecx = start of area to print, edx = length
90 281 mov eax,__NR_write ; write syscall
91 282 int 80h
92 284 mov ecx,[errmsgnl] ; newline
93 285 mov edx,1 ; 1 char long
94 286 mov eax,[__NR_write] ; write syscall
95
96 Program received signal SIGSEGV, Segmentation fault.
97
98 Okay, easy fix. I also noticed I stll had the operands
99 transposed on line 273. And I swapped out the double
100 quotes around the errmsgnl string literal to backquotes
101 as required by NASM for backslash escape support.
102
103 Let's see how it goes now:
104
105 Continuing.
106 foo
107 PARSE ERROR: foo
108
109 [Inferior 1 (process 2582) exited normally]
110
111 Yay!
112
113
114
115