pagetable.com is a new blog about assembly language. They even do puzzles!

I think I kind of know the answer to the first one. Wouldn’t something like this work, with x and y in ax and bx?

mul ax, bx jz label

Well, probably not. I haven’t touched x86 assembly since 1995 or so, my memory is not good, and I have absolutely no clue how things with more than 16 bit are done. Um, use two registers for 32 bit? And my solution is bad anyway because multiplication is so expensive. At least it was back in my days. Or has Intel fixed that by now?

16 bit should be enough for anybody, really.

(via Martin Ott)

I wrote the puzzle entry. Your result is the same basic idea as mine.

“mul” makes a double-sized result. It multiplies ax times whatever your parameter is (you generally don’t write the “ax, ” because mul only works this way). The size of a multiplication result (product) is always the sum of the multiplicands’ sizes – in this case double the size. To avoid losing this data – which in some cases is very useful – the processor stores both the “high” and “low” result. The high result goes into dx, and the low result goes into ax. You can’t choose which registers, unfortunately.

The problem with your code is when you have values that multiply to a result that is 0 in the low part, such as 256 * 256 (decimal). A quirk of the x86 is that the “mul” instruction sets the zero flag based on the low part of the result, not the whole result. So 256 * 256 wouldn’t work with your code.

To fix it, you do “or ax, dx”, or similarly “or dx, ax”. This destroys any meaningful value the multiplied value once had, but sets the zero flag if and only if both halves were 0 – which can only happen when one or both variables started out 0.

As for 32 bits, it’s not too hard. You have 32 bit registers “eax”, “ebx”, “ecx”, etc. instead of “ax”, “bx”, “cx”. “ax” represents the low 16 bits of “eax”, much like “al” represents the low 8 bits of “ax”. There is no way to directly access the high 16 bits of eax however, unlike “ah” with “ax”.

Going even further, the same applies to 64 bits (AMD64). Now we have “rax”, “rbx”, “rcx”, etc. of which “eax”, “ebx”, “ecx” are the low 32 bits. AMD64 also adds 8 whole new registers. Since the concept of assigning particular meanings to registers is long obsolete, the new registers were simply named “r8” to “r15”. “r0” to “r7” are aliases for the original 8: “r0” is “rax”, “r1” is “rcx”, etc.

-myria (Melissa)

Thanks for the refresher M.! A pity I forgot about the zero flag quirk. Hope you do a C64 assembler puzzle one of these days, then I’ll have to dig through some *really* ancient parts of my memory …

/me goes off to find a good online opcode reference

Yes, I will definitely do 6502 and 65816 puzzles. =)

-myria