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