Since much of this exercise revolves around writing C programs and examining their assembly, there aren't a lot of "solutions" but we did ask you a few pointed questions.
1. What does CLTD
do? There are many references online for x86
assembly. I (Margo) often find that googling "intel x86 eax
and performs sign
extension into edx
, forming a double word (8 bytes). Now, you may
wonder why it does this. Stay tuned for the next question!
2. Why does idivl
take only one operand?
The short answer is that the second operand is implied. The slightly
longer answer is that idivl
has a lot of details implied in the
instruction. In particular, the dividend (i.e., numerator) depends on
the size of the divisor (denominator). If we are dividing by an 8-bit
quantity, we use the IDIVB
instruction and we then must place the
dividend in %ax (the low 16 bits of %eax); if we are dividing by a
16-bit quantity, we use IDIVW
and must place the dividend in 32-bits
formed by the combination of the DX and AX registers. Finally, and of
interest here, if we are dividing by a 32-bit number, we use IDIVL
and
place the dividend in the combination of the EDX and EAX registers.
You may wonder why we require that the dividend be a larger location than the divisor -- the explanation is that it allows an N-bit architecture to handle the full range of multiplication by 2 N-bit numbers as well as division of the result of a multiplication by an N-bit number.
3. How are signed and unsigned values treated differently?
They mostly aren't, except when we have types smaller than a register we have to either sign-extend (for signed values) or 0-extend (for unsigned values) into the larger register.
4. How are operands of different sizes treated differently?
In general it simply means we use different suffixes on our instructions
(e.g., ADDW
instead of ADDL
). Sometimes it means we need to perform
sign/zero extension -- see previous question.
5. (In reference to 6.s) Note that although the second parameter is unsigned, the assembly code moves only a single byte in %cl. Why? Since we only have 32-bits in a register, shifting more than 32 places doesn't make sense. As a result, the size of the operand telling you how many bits to shift need only by 1-byte.