If all the OP's examples use the global $_ then printing it at the end would show the last value assigned. What actually happens is a warning for 'Use of uninitialized value $_ ...' The subroutine uses whatever $_ that is in scope when it is called.
$_ = 'x';
my $loopvar = 'in the loop';
print "\$_ = $_\n"; # warning for uninitialized value $_ (global scop
print "\$_ = $_\n"; # prints $_ = x