How can I become good at assembly?-Collection of common programming errors
First, how do one define “good assembly code”? The fastest code, the most ABI compliant code, or the code which is easiest to read? I think “good” depends on the overall goal, and you didn’t really tell us what you want to use assembly for.
Others recommended writing a software rasterizer. I could latch onto that, but since you already know the x86 mnemonics, you don’t really need to write more assembly code. What you need is more insight in how machines work under the hood.
My suggestion is to write a system-wide or user-space emulator. I wrote a system-emulator for ARM920, and learned a ton, without writing a single assembly mnemonic! Okay, it ended up dead slow, but I wrote it as an interpreter in pure C. I now know most of the ARM architecture’s dark secrets and it gave me a new perspective on how embedded computers work.
Just remember, peripherals can be complex to emulate. There is nothing wrong with emulating the CPU, but adding simplified psuedo-peripherals. If you’re good, you could even make a plug&play system for them.
You might want to check out the QEMU and DosBox sources to get some good ideas, though they use a JIT scheme. My interpreter is found here gp2xemu. It was an attempt at an emulator for the GP2x, but I got stuck due to sucky documentation.