深入理解计算机系统第三章--程序的机器级表示
练习题解析
3.1
假设下面的值存放在指明的内存地址和寄存器中:
操作数 值 注释 %eax 0x100 寄存器 0x104 0xAB 绝对地址 $0x108 0x108 立即数 (%eax) 0xFF 地址0x100 4(%eax) 0xAB 地址0x104,4+(%eax) 9(%eax,%edx) 0x11 地址0x10c,9+%eax+%edx 260(%ecx,%edx) 0x13 地址0x108,260d=0x104 0xFC(,%ecx,4) 0xFF 地址0x100,0xFC+4*%ecx (%eax,%edx,4) 0x11 地址0x10c,%eax+4*%edx 3.2
对于下面汇编代码的每一行,根据操作数,确定适当的指令后_缀。(例如, mov可以被重写成 movb、 movw、 mov‘或者 movq。)movl %eax,(%esp) movw (%eax),%dx movb $0xFF,%bl movb (%esp,%edx,4),%dh pushl $0xFF movw %dx,(%eax) popl %edi
3.3
当我们调用汇编器的时候,下面代码的每一行都会产生一个错误信息。解释每一行都是哪里出了错。错例 解析 movb $0xF,(%bl) %bl不能作为地址单位,因为它只有一字节,而IA-32的地址是32位的。 movl %ax,(%esp) %ax只有一个字长,而movl是用来传送双字的,这里应该用movw。 movw (%eax),4(%esp) %eax和%esp为双字长,而movw用来传送单字,这里应该用movl movb %ah,%sh 没有%sh这个寄存器 movl %eax,$0x123 立即数不能作为目的操作数 movl %eax,%dx %eax为双字长,而%dx为单字长,不能互相传送 movb %si,8(%ebp) %si为单字长,而movb用来传送单字节,这里应该用movw 3.4
假设变量 sp和 dp被声明为类型
src_t sp;
dest_tdp;
这里 src t和 dest t是用 typedef声明的数据类型。我们想使用适当的数据传送指令来实现下面的操作
dp= (dest_t) sp;
假设 sp和 dp的值分别存惜在寄存器宅rdi和毛rsi中。对于表中的每个表项, 给出实现指定数据传送的两条指令。 其中第一条指令应该从内存中读数, 做适当的转换, 并设置寄存器%rax的适当部分。然后,第二条指令要把宅rax的适当部分写到内存。在这商种情况中, 寄存器的部分可以是%rax、%eax、%ax或%al, 两者可以互不相同 。
记住, 当执行强制类型转换既涉及大小变化又涉及 C语言中符号变化时, 操作应该先改变大小(2. 2. 6节)。src_t dest_t 指令 int int movl %eax,(%edx) char int movsbl %al,(%edx) char unsigned movsbl %al,(%edx) unsigned char int movzbl %al,(%edx) int char movb %eal,(%edx) unsigned unsigned char movb %eal,(%edx) unsigned int movl %eax,(%edx) 3.5
void decode1(int *xp,int *yp,int *zp) { int x = *xp; int y = *yp; int z = *zp; *yp = x; *zp = y; *xp = z; }
3.6
假设寄存器%eax的值为,%ecx的值为y。填写下表,指明下面每条汇编代码指令存储在寄存器%edx中的值:指令 结果 leal 6(%eax),%edx x+6 leal (%eax,%ecx),%edx x+y leal (%eax,%ecx,4),%edx x+4y leal 7(%eax,%eax,8),%edx 9x+7 leal 0xA(,%ecx,4),%edx 10+4y leal 9(%eax,%ecx,2),%edx x+2y+9 3.7
假设下面的值存放在指定的存储器地址和寄存器中
填写下表,给出下面指令的效果,说明将被更新的寄存器或存储器位置,以及位置的值指令 目的 值 解析 addl %ecx,(%eax) 0x100 0x100 这条指令的目的操作数(%eax)是寄存器%eax的值0x100(视为一个指针)所指向的值,所以地址0x100中的值被更新了,新的值为0xFF加上寄存器%ecx的值(视为一个数)0x1,等于0x100。 subl %edx,4(%eax) 0x104 0xA8 这条指令的目的操作数4(%eax)是寄存器%eax的值加上4即0x104(视为一个指针)所指向的值,所以地址0x104中的值被更新了,新的值为0xAB减去寄存器%edx的值(视为一个数)0x3,等于0xA8。 imull $16,(%eax,%edx,4) 0x10c 0x110 这条指令的目的操作数4(%eax)是寄存器%eax的值加上4即0x104(视为一个指针)所指向的值,所以地址0x104中的值被更新了,新的值为0xAB减去寄存器%edx的值(视为一个数)0x3,等于0xA8。 incl 8(%eax) 0x108 0x14 这条指令的目的操作数8(%eax)是寄存器%eax的值0x100加上8即0x108(视为一个指针)所指向的值,所以地址0x108中的值被更新了,新的值为0x13自增一等于0x14。 decl %ecx %ecx 0x0 这条指令的目的操作数%ecx是寄存器%ecx的值0x1,所以寄存器%ecx被更新了,新的值为0x1自减一等于0x0 subl %edx,%eax %eax 0xFD 这条指令的目的操作数%eax是寄存器%eax的值0x100,所以寄存器%eax被更新了,新的值为0x100减去寄存器%edx的值0x3等于0xFD。 3.8
movl 8(%ebp),%eax ;取出x的值 sall $2,%eax ;x左移两位 movl 12(%ebp),%ecx;将n的值放进%ecx中 sarl %cl,%eax ;将x向右移动cl中的值个单位,因为只允许移动0~31位,所以只能移动cl中的值个单位(最多为15)而不能移动%ecx中的值个单位(最多为2^32-1),否则可能出错。
3.9
int arith(int x,int y,int z) { int t1 = x^y; int t2 = t1 >> 3; int t3 = ~t2; int t4 = t3-z; return t4; }
3.10
3.11
3.12
3.13
3.14
3.15
3.16
3.17
3.18
3.19
3.20
3.21
3.22
3.23
3.24
3.25
3.26
3.27
3.28
3.29
3.30
3.31
3.32
3.33
3.34
3.35
3.36
3.37
3.38
3.39
3.40
3.41
3.42
3.43
3.44
3.45
3.46
3.47
3.48
3.49
3.50
3.51
3.52
3.53
家庭作业解析
3.54
int t1 = z; int t2 = t1 - z; int t3 = t2; int t4 = t3 << 15; int t5 = t4 >> 15; int t6 = t2 ^ x; int t7 = t5 * t6; return t7;
3.55
1 movl 12(%ebp),%esi ;取x的低32位 2 movl 20(%ebp),%eax ;取y 3 movl %eax,%edx ;将y复制到%edx中 4 sarl $31,%edx ;取y的最高位即符号位 5 movl %edx,%ecx ;将y的符号位复制到%ecx中 6 imull %esi,%ecx 7 movl 16(%ebp),%ebx;取x的高32位 8 imull %eax,%ebx ;x的高32位乘以y 9 addl %ebx,%ecx ; 10 mull %esi 11 leal (%ecx,%edx),%edx 12 movl 8(%ebp),%ecx 13 movl %eax,(%ecx) 14 movl %edx,4(%ecx)
语句 %eax %ebx %ecx %edx %esi 1 x的低32位 2 y x的低32位 3 y y x的低32位 4 y y的符号位 x的低32位 5 y y的符号位 y的符号位 x的低32位 6 y y的符号位 * x的低32位 y的符号位 x的低32位 7 y x的高32位 y的符号位 * x的低32位 y的符号位 x的低32位 8 y x的高32位 * y y的符号位 * x的低32位 y的符号位 x的低32位 9 y x的高32位 * y y的符号位 * x的低32位+x的高32位 * y y的符号位 x的低32位 10 x的低32位 * y x的高32位 * y y的符号位 * x的低32位+x的高32位 * y y的符号位 x的低32位 11 x的低32位 * y x的高32位 * y y的符号位 * x的低32位+x的高32位 * y y的符号位 + y的符号位 * x的低32位+x的高32位 * y x的低32位 12 x的低32位 * y x的高32位 * y * dest y的符号位 + y的符号位 * x的低32位+x的高32位 * y x的低32位 13 14 3.56
3.57
3.58
3.59
3.60
3.61
3.62
3.63
3.64
3.65
3.66
3.67
3.68
3.69
3.70