user-0 提问: 《深入理解计算机系统（第二版）》 练习题3.18疑惑求教

回复:
user: user-1
content: 楼主，我按照你的代码（不是书上的标准答案），写了程序，在虚拟机上编译成汇编，我看到你的结果和书上的汇编很相似，反而是书上标准答案编译成汇编，不符合书上的汇编代码的结果。我感觉书上是不是错了啊。 按照楼主的C代码，编译出的汇编代码是这样的：  （注意看.L2） 	.file	"18.c" 	.text .globl test 	.type	test, @function test: 	pushl	%ebp 	movl	%esp, %ebp 	subl	$16, %esp 	movl	12(%ebp), %eax 	movl	8(%ebp), %edx 	movl	%edx, %ecx 	subl	%eax, %ecx 	movl	%ecx, %eax 	movl	%eax, -4(%ebp) 	cmpl	$-3, 8(%ebp) 	jge	.L2 	movl	12(%ebp), %eax 	cmpl	8(%ebp), %eax 	jge	.L3 	movl	8(%ebp), %eax 	imull	12(%ebp), %eax 	movl	%eax, -4(%ebp) 	jmp	.L4 .L3: 	movl	12(%ebp), %eax 	movl	8(%ebp), %edx 	leal	(%edx,%eax), %eax 	movl	%eax, -4(%ebp) 	jmp	.L4 .L2: 	cmpl	$2, 8(%ebp) 	jg	.L4 	movl	12(%ebp), %eax 	movl	8(%ebp), %edx 	xorl	%edx, %eax 	movl	%eax, -4(%ebp) .L4: 	movl	-4(%ebp), %eax 	leave 	ret 	.size	test, .-test 	.ident	"GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)" 	.section	.note.GNU-stack,"",@progbits

user: user-2
content: 理解和讨论之前请先学会如何观察！

user: user-2
content: 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

user: user-0
content: 楼上能具体解释下吗，谢了

user: user-3
content: 晕，“ int val = x*y;” 和 “ int val = x ^ y;”不同，反正code path的白盒测试要过

user: user-4
content: 1 楼正解呀  另外你说的汇编代码第3,4行，%eax 与 -3比较，即 x >= -3（jge） 时是跳到L2，如果x < -3 则往下继续执行，也即汇编代码第五行 cmpl %edx, %eax 翻译就是campare x and y 再第六行，就是如果 x <= y 调到L3 如果x > y 继续执行 imul x , y  剩下的就不多说了 所以答案肯定是if(x<-3)

user: user-0
content: 那是为什么呢

user: user-4
content: 引用 4 楼 wjiech 的回复:我的意思是习题答案可不可是以下代码呢？ 1    int  test(int x, int y) { 2          int val = x*y; 3          if ( x >= -3) { 4             if(x>2)  5                 val = x - y; 6             else  7                    val = x ^ y; 8          }  else if(x<=y) { 9                      val = x + y; 10        return val; 11 }  不行

user: user-0
content: 我的意思是习题答案可不可是以下代码呢？ 1    int  test(int x, int y) { 2          int val = x*y; 3          if ( x >= -3) { 4             if(x>2)  5                 val = x - y; 6             else  7                    val = x ^ y; 8          }  else if(x<=y) { 9                      val = x + y; 10        return val; 11 }

user: user-0
content: 汇编代码如下 x at %ebp+8, y at %ebp+12 1     movl    8(%ebp), %eax 2     movl    12(%ebp), %edx  3     cmpl     $-3, %eax 4     jge       .L2 5     cmpl    %edx, %eax 6     jle        .L3 7     imull    %edx, %eax 8     jmp     .L4 9  .L3: 10   leal     (%edx, %eax), %eax 11   jmp       .L4 12 .L2: 13   cmpl    $2, %eax 14   jg       .L5 15   xorl    %edx, %eax 16   jmp      .L4 17 .L5: 18   subl     %edx ,   %eax 19 .L4:   按user-5同学所述，汇编代码第3、4行,寄存器eax的内容和立即数-3比较后是用的jge,而书中答案为何是if(x<-3)呢？

user: user-5
content: 这位同学，你好像忘了贴汇编的代码了，我看了一下习题，请注意第14行的汇编，在eax寄存器中的内容和立即数2比较之后，使用的是jg跳转指令，如果使用你的写法，那么对应的汇编将是jle，当然下面的汇编也会相应更改。