scanf("%c");
That for sure can crash. It reads a char and places it to random location in memory.
The example code is very very old. It lacks __interrupt __saveds for the interrupt code (vbinter).
I'm also not understanding vBlankInterrupt.is_data is used for. Is it like DOS where when you have an interrupt you have no clue where your data segment points? That can't be right.
is_Data is used to pass a user controlled data to the interrupt routine (it arrives in A1 register). Typically this is used if the code cannot use static variables (and thus __saveds cannot be used), for example where there might be several different interrupts added, each with unique instance data.