Decoding instructions is not that complicated. However, because the Intel family of processors are CISC, it makes the task rather daunting.
First of all, you should not write it in assembler, because it's going to take you a year or two, but maybe you have the time to do that. Since you only need to scan the code, not print out the results, you can do the work much faster than an actual disassembler would do. That being said you'll bump in the same main problems.
First of all, the manuals are there:
http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html?iid=tech_vt_tech+64-32_manuals
I suggest this one:
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
Then, all you have to do is read one byte and understand it. You have a table on page 770 that shows you the encoding from the op-code to the instruction.
So for example, 0x33 represents an XOR with Gb,Ev as parameters. G means General register defined in the following ModR/M. Then the b is the size (byte). The E means that you have a ModR/M after that one byte (same byte for G and E). So you will have to read that one byte to determine the addressing mode and from that you can determine the register (Can be ignored) and the address size. The address (Ev) may be another register (then no extra byte), it could be immediate data (1, 2, 4, 8 bytes) or it could be an address (again 1, 2, 4, 8 bytes). Pretty simple, right? Note that ALL instructions use the exact same ModR/M so you have to implement that just once. Also the order in which bytes are added after the instruction code is always exactly the same.
Before the address or immediate (if I'm correct) comes the extra Mod for 64 bit instructions. That one defines additional modes and support for the extended registers. All of that is described in detail in the document I mentioned earlier.
More or less, you need your parser to understand the ModR/M, SIB, prefixes, and voilà. It's not that complicated. Then the first byte tells you the instruction (first 2 bytes if the first byte is 0x0F...)
Some instructions also support prefixes to tweak the size of the operands and other similar things. As far as I know, only the 0x66 (op size) and 0x67 (addr size) have an effect on the size of the address and immediate data. The other prefixes will not affect the number of bytes used by the instruction so you can simply ignore them (well count them, but no need to know what follows).
All of that said, using the LLVM library (As someone mentioned in the comments) is probably a better/easier option, although it may be much bigger than what you'd need if your stuff is limited.