The short answer is that it's not possible in the general case.
The longer answer is that you can attempt to disassemble the jump table that the contract begins with if the contracts follows the Ethereum ABI, contracts don't have to follow it to be accepted by miners, but all smart contracts in use will follow this ABI.
So you attempt to locate the jump table in the beginning of the code, and then you compare the four bytes you refer to in your question with a lookup table of known function signatures.
Then you have to start building this lookup table by scouring through contract standard definitions, like ERC20, ERC721 etc. So if you find a the four bytes a9059cbb
in the lookup table, the contract most likely has a method called transfer
which takes an address
and a uint256
argument since keccak256("transfer(address,uint256)") = 0xa9059cbb
.
Be aware that the hashed function signature is so small that it's possible to make collisions if you would want to.
For more context, see Why does compiled solidity code do this check on the argument with which it was called?