tx.origin should be used in EXTREMELY rare circumstances. When you check
tx.origin you are checking who the call originated from, so if used improperly it can open up extreme vulnerabilities, or possibly break functionality in your contract.
person a -> contract-a -> contract-b if you check
contract-b it will resolve to the address of
person a not the address of
contract-a. If you check
msg.sender it will be
The reason why assembly is used, as you point out, is that there currently exists no solidity built in functions to handle that. Solidity is still quite a young language, so it's not surprising.
with regards to not having a contract being able to call itself
There's only a few ways this can happen:
1) Specifically programming functions or logic that forces the contract to call itself
2) Making call to unknown contracts that can trigger fallback code execution
Option 1 isn't really a problem since that's very easy to control, but Option 2 can open you up to hacking attempts on your contract since the unknown contract you're calling could conceivably implement a fallback function which would trigger calls to your contract.
I think your problem would better be resolved by findings which functions allow the contract to call itself, and change those functions, while removing any calls to unknown contracts that could trigger code execution for which you don't know the outcome. You could implement some assembly wizardry to prevent this from happening, but to me that sounds like it opens you up to potential vulnerabilities.