One of the very best ways you can report a bug is by showing it directly to the developer - either in person, or via a remote support session (like webex). Demonstrate the exact thing that goes wrong. Let them watch you run the software, watch how you interact with the software, and watch what the software does in response to your inputs.
They [should] know that software like the back of their hand: which parts they trust, and which parts are most likely to have faults. Intuitively, they know what to watch for. By the time the software does something obviously wrong, they may well have already noticed something subtly wrong earlier which might give them a clue. They can observe [almost] everything the system does during the test run, and they can pick out the important bits for themselves.
This may not be enough. They may decide they need more information, and ask you to show them the same thing again. They may ask you to talk them through the procedure, so that they can reproduce the bug for themselves as many times as they want. They might try varying the procedure a few times, to see whether the problem occurs in only one case or in a family of related cases. If you're unlucky, they may need to sit down for a couple of hours with a set of development tools and really start investigating. But the most important thing is to have the programmer looking at the computer when it goes wrong. Once they can see the problem happening, they can usually take it from there and start trying to fix it.
If you have to report a bug to a programmer who can't be present in person (or via remote support tools), then you want to ensure they can reproduce the problem. If they can't, they may have to assume that there's a user error.
Report exactly what you did leading up to the error. If it's a graphical program, report exactly which buttons you pressed, and in what order you pressed them. If it's a command-line program, capture precisely what command you typed - this is where tools like `script` and `tee` can again come in handy!
Make sure the bug report has all the input you can think of. If the program reads from a file, add a copy of the file. If the program talks to another computer over a network, while you can't send a copy of that device, you can report what kind of system it is, and (if you can) what software is running on it.