Okay, let's step through your program line by line. I'm also assigning unique numbers (think of them as object addresses, if you're used to C-like languages) for each newly-created object so you can see what's what. :-)
(define x (list 1 2 3)) ; => #1 = (1 . #2), #2 = (2 . #3), #3 = (3 . ())
(define y (list 4 5)) ; => #4 = (4 . #5), #5 = (5 . ())
(define z (cons (car x) (cdr y))) ; => #6 = (1 . #5)
(define w (append y z)) ; => #7 = (4 . #8), #8 = (5 . #6)
(define v (cons (cdr x) (cdr y))) ; => #9 = (#2 . #5)
(set-car! x 6) ; => #1 = (6 . #2)
(set-car! y 7) ; => #4 = (7 . #5)
(set-cdr! (cdr x) (list 8)) ; => #2 = (2 . #10), #10 = (8 . ())
Now, let's look at your values (for each reference, use the last assigned value):
x ; #1 => (6 . #2) => (6 . (2 . #10)) => (6 2 8)
y ; #4 => (7 . #5) => (7 5)
z ; #6 => (1 . #5) => (1 5)
w ; #7 => (4 . #8) => (4 . (5 . #6)) => (4 . (5 . (1 . #5))) => (4 5 1 5)
v ; #9 => (#2 . #5) => ((2 . #10) 5) => ((2 8) 5)
Edit: I'm adding a diagram to explain my answer, since you can't have diagrams in a comment. I don't have time to make a diagram showing the values above, but this hopefully explains a few things.

Each pair has two "slots", car
and cdr
, represented as the left and right boxes in the diagram above. Each of these slots, as you see, has three possible things:
- An atom (a number in your examples, or symbols in the diagram, such as
let
, s5
, and sqrt
)
- A reference (represented as an arrow in the diagram)
- Null (represented as a black box in the diagram)
You can put any of these in any of the slots. So, in my explanation above, each of the #
items is an arrow, each of the non-#
numbers is an atom, and each of the ()
is a black box. So, in the line
(define v (cons (cdr x) (cdr y)))
you are creating a pair, where the left-hand slot has the same contents as the right-hand slot of x
(i.e., an arrow going to pair 2), and the right-hand slot has the same contents as the right-hand slot of y
(an arrow going to pair 5). In other words, both boxes in v
contain arrows, each going off a different pair.
Hope this makes more sense. :-)
remember that each variable doesn't hold a list, they hold just a cons
cell. a list (or a tree) is a composite structure of several cons cells, some of which may be shared between several structures.
also, you're thinking about pointers and references, instead of thinking about values, which can be either immutable values (like numbers, or symbols) or mutable values (like conses or strings) mutable values are allocated, garbage collected and passed by reference.
one last point to remember: the cons
procedure always allocates a new cons cell.
after (define z (cons (car x) (cdr y)))
, z holds a brand new cons with the same as x and the same car as x, and the same cdr as y. when you (set-car! x)
, you just change the x cons cell, not z.
after (define v (cons (cdr x) (cdr y)))
, v holds a brand new cons whose car is the same value as the cdr of x; that is a cons cell. the very same cons cell as (cdr x). it's shared by the two lists. when that shared cons cell is modified by (set-cdr! (cdr x) ...)
, both lists are affected.