2
votes

I'm reading the book "Computer Systems: A Programmer's Perspective". Right now I'm not really sure I understand when to use the different mov instructions. Here's the exercise:

Practice Problem 3.4

Assume variables v and p declared with types

src_t v;

dest_t *p;

where src_t and dest_t are data types declared with typedef. We wish to use the appropriate data movement instruction to implement the operation

*p = (dest_t) v;

where v is stored in the appropriately named portion of register %eax (i.e., %eax, %ax, or %al), while pointer p is stored in register %edx.

For the following combinations of src_t and dest_t, write a line of assembly code that does the appropriate transfer. Recall that when performing a cast that involves both a size change and a change of “signedness” in C, the operation should change the signedness first (Section 2.2.6).

I'm checking my solutions against this blog post and I'm not quite sure I understand problem 3:

src_t       dest_t      My Solution              Blog's Solution

char        unsigned    movzbl %al, (%edx)     movsbl %al, (%edx)

Number 3: I use movzbl while the blog's author uses movsbl. I don't understand the reasoning of movzbl vs movsbl in this case... If the char is a negative you'll end up with a wrong number either way, can anyone clarify why movsbl is the correct choice here?

1
That depends entirely whether char is signed or unsigned. That is implementation-defined, so both solutions are equally correct, given the matching implementation. - Jester
@Jester I think char is signed in this case, other problems have unsigned char so I think the lack of it means this one is signed. - Augusto Dias Noronha
If char is signed, you need to use movsbl to sign extend it. For example, if your char value is -1 you want the unsigned int value to be 0xffffffff (this is mandated by the C standard). - Jester
I see... It wasn't quite clear for me what the rules were in this case. Thank you for your help - Augusto Dias Noronha

1 Answers

1
votes

Recall that when performing a cast that involves both a size change and a change of “signedness” in C, the operation should change the signedness first (Section 2.2.6).

Unless I'm misreading it, this sentence appears to conflict with what he gives as the correct answer.

That rule would mean that, starting with signed char:

  • signed char
  • -> unsigned char
  • -> unsigned int

So the size conversion is from unsigned char to unsigned int, so movz would be appropriate. Presumably the rule is wrong (doesn't match what C actually specifies), and movs really is what a C compiler would use.

Jester's comment says that the unsigned int value of a -1 char value is required to be 0xffffffff, so it looks like that last sentence of the practice problem about order of converting signedness and size is the problem.