possibly a bit late, but if it's still of use. . .
Alter procedure tabproc
EXEC('Select count(*) from ' + @tablename + ' where isactive = 0' )
Basically the code in the exec statement is creating a string which contains your statement - you're concatenating the string value held by the variable @tablename with the rest of the statement. Once concatenated, this new string is sent to the exec command, which runs the string as if it had been typed as a statement.
I also changed the type of @tablename from varchar(500) to sysname. That's not required, but is the "correct" data type for holding object names. I doubt it affects performance, but it may give you a little future proofing on SQL upgrades, should the allowed table name length ever change.
Seggerman suggested dynamically creating a synonym. That's a nice idea, but may have concurrency issues (e.g. if the same code is called to run for two different tables at the same time your synonym may be incorrectly updated for one thread by the other). Also, I suspect this may have adverse affects on performance. I'm not a DB expert though, and haven't experimented, so these may not be problems.
Hope that helps,