Although not as regular as some RISCs, x86 is still quite regular which makes it relatively easy to write an assembler for; the main opcode space is octal-structured (http://www.dabo.de/ccc99/www.camp.ccc.de/radio/help.txt) and nearly 1/4 of the single-byte opcodes, 00-3F (0xx in octal) are where all the frequently-used ALU ops (reg-reg, reg-mem, mem-reg) reside. The ability to easily generate vast swaths of the opcode space from a compact description is what makes a table-driven (dis)assembler easy to write.
Related, an x86 (self-)disassembling demo in 256 bytes: http://www.pouet.net/prod.php?which=16930