The execute bit permission is checked by the kernel on executing the exec(2) (and cousins) system call. You will need it only to execute programs at the kernel level.
Only programs with that bit on (whichever hits to you as the owner, group or others is what is being checked) can be exec()ed by the kernel.
Other different thing is what the shell does when interpreting a shell script or perl, or whatever interpreter may you have. On scripts, the kernel checks the
#!... at the beginning of the file as a magic number, and launches the shell indicated there (you will need execute permission for the shell also), and you do need read permissions on that script, as the shell has to open it and read it to be interpreted. For shell scripts you'll need read permission as well as executing permission. But for shell scripts you only need read permission, as you always are able to execute a shell script by executing the shell and passing the shell script as a parameter (or input file)
Of course, as it has been pointed to, the execute bit can be circunvented by copying the program and making it executable, but you'll not be able to copy it if you don't have read permissions to make that copy (you continue to be able to execute it).
Try to change (as root of course) permissions to ls(1) and make it
---x--x--x) and try to do an executable copy of it, and see how you cannot get your executable copy, even when you continue to be able to execute it.
On directories, execute bit means a different thing. The kernel uses '
x' permission when iterating through the path (in the namei() kernel function) so if you don't have execute permissions on a directory, you cannot either use it, nor the files accessible through it. Even you can read a directory contents with read permissions, but you cannot access the files in it. Or at the opposite, you can have execute permissions on a directory but not read access, and you'll be able to use the files inside, but you'll not be able to see the directory contents.