I prefer working from under the floor when possible. Although it is easier to screw loose flooring down from the top, it is often difficult to fill the holes and make the color and finish match. Using the top down method is a last resort, especially if you have a large area to secure. The Counter Snap screws mentioned in the previous answer are great devices, but commonly used to secure squeaky sub-floors under carpet. They will work on wood, but prefer a counter-sunk finish screw. With finish screws, you can control the counter sink depth and the head is about the same size as a finish nail.
Using blind screws from the bottom is a common way to attack your problem. The method of "pulling" the finish floor snug is important. I have used drywall screws many times with great success. You have to be very careful to calculate the thickness of the subfloor and finish hardwood, so the screw does not protrude through the floor. If in fact the subfloor is pine or soft wood, a drywall screw may be a bad choice as they can be aggressive and counter sink themselves too deep. Remember, the goal is to pull the finish floor down snug. This can be done by predrilling holes in the subfloor at the same or 1/32" larger than the diameter of the screws. That way, the screws are only threading into the finish floor, not the subfloor. When the screw head contacts the bottom of the subfloor, all force pulls the finish floor down to the subfloor. You can use a collet or a piece of tape on your drill bit to gauge the depth of your holes and not go into your finish flooring. Rather than a countersinking screw, like a drywall screw, use a #8 panhead screw sized to only penetrate the finish floor 1/2" (for 3/4" flooring). Just tighten the screws enough to make them snug, don't try to over-tighten them as that may cause them to strip out. Plan on using quite a few screws. I usually start by spacing them 8 to 10 inches apart. In stubborn areas where the squeak just wont go away, you may need to add a few more screws. Good Luck.