Call shape: personal_sign with parameters [message, address], where the message is hex-encoded bytes (most wallets also accept UTF-8 text). Libraries mirror it: ethers signer.signMessage, viem signMessage, web3.py encode_defunct. The older eth_sign signed an arbitrary 32-byte hash without a prefix, letting dapps trick users into signing transactions, and most wallets disable or warn about it.
Verification recomputes the prefixed Keccak-256 hash and recovers the address, or calls ERC-1271 isValidSignature (wrapped in ERC-6492 for undeployed accounts) for smart wallets. Sign-In with Ethereum messages are signed this way.