More specifically: .COM infectors we super easy to write because they didn't have a huge header to deal with (like .exes did): code started at address 0x0100 and that's all. At least that's how I recall it.
So an infector just loaded up a .COM file, changed 0x0100 so it was a jump to the end of the .COM file, and then appended the entire infector's code to the end of the .COM file. Finally, you append the very first instruction you overwrote, and a jump back to the beginning. And that's it, now the .COM is itself an infector. To not be obvious your infector should only infect a few .COMs at a time, otherwise your 486 would slow to a crawl hunting up files to infect.
Of course, you could get more interesting (terminate and stay resident, more aggressively self-modifying code, etc), but that was the simplest virus I remember seeing.