CSAPP 习题3.4
题目
假设变量sp和dp被声明为类型
src_t *sp;
dest_t *dp;
这里src_t和dest_t是用typedef声明的数据类型。我们想使用适当的数据传送指令来实现下面的操作
*dp = (dest_t) *sp;
假设sp和dp的值分别存储在寄存器%rdi和%rsi中。对于表中的每个表项,给出实现指令数据传送的两条指令。其中第一条指令应该从内存中读数,做适当的转换,并设置寄存器%rax的适当部分。然后,第二条指令要把%rax的适当部分写到内存。在这两种情况中,寄存器的部分可以使%rax、%eax、%ax或%al,两者可以互不相同。
记住,当执行强制类型转换既涉及大小变化又涉及C语言中符号变化时,操作应先改变大小。
src_t | dest_t | 指令 |
---|---|---|
long | long | movq (%rdi),%rax movq %rax,(%rsi) |
char | int | |
char | unsigned | |
unsigned char | long | |
int | char | |
unsigned | unsigned char | |
char | short |
解答
这个题目本身不难,但是有一点很绕,什么时候用符号扩展传送指令,什么时候用零扩展传送指令
首先,根据左右两个的最大长度来判断是%rax、%eax、%ax还是%al。如:char是一字节,int是双字,所以用%eax;char是一字节,short是一字,所以用%ax。
我们一行一行解答
1. char -> int
首先char是有符号类型,int也是有符号类型,所以可以肯定需要符号扩展传送指令,由于char是1字节,而int是是双字,所以结果应该为
movsbl (%rdi),%eax
movq %eax,(%rsi)
2. char -> unsigned
由于char是有符号类型,unsigned是无符号类型,那么一个有符号一个无符号,我怎么选择扩展指令呢,这是题目的那句,记住,当执行强制类型转换既涉及大小变化又涉及C语言中符号变化时,操作应先改变大小。,所以我们应该先改变大小,改变有符号数的大小还是应该用movqs指令,所以结果与上面相同,
movsbl (%rdi),%eax
movq %eax,(%rsi)
3. unsigned char -> long
现在又来了,第一个是无符号数,第二个是有符号数,第一个是一字节,第二个是4字,根据上面的原则应该先改变大小,
movzbq (%rdi),%eax
movq %rax,(%rsi),
等等为什么答案不对,为什么答案是
movzbl(%rdi),%eax
movq %rax,(%rsi)
课本P123页给出,movl指令以寄存器作为目的时,它会把该寄存器的高位4字节设置为0。大意是把32位扩展到64位。
4. int -> char
这个基本上就没有什么要讲的了,int有符号,char有符号,也不需要扩展,
movl (%rdi),%eax
movq %al,(%rsi)
5. unsigned -> unsigned char
这个答案也很简单,
movl (%rdi),%eax
movq %al,(%rsi)
6. char -> short
这个也不难了,char是有符号一个字节,short是有符号的一个字,所以答案是
movsbw (%rdi),%ax
movw %ax,(%rsi)
来源:https://www.eutaboo.com/index.php/2020/07/23/csapp-%e4%b9%a0%e9%a2%983-4/
文章版权归作者所有,未经允许请勿转载。


