摘自csapp 3.15.1。
这两个程序的目的判断32位乘法是否溢出,因为imull和mull在溢出时都会将CF标志设为1,setae命令设置al为~CF,最后返回eax判断是否溢出。
但是,这两个程序在 gcc4.4 下都不能按csapp原意编译(作者也说正确编译靠编译器的理解)
第一个程序,编译器认准了result = 0,无论加不加 -O -O2命令,最后都会把eax设为0
int ok_smull(int x, int y, int *dest) {
int result = 0;
*dest = x*y;
asm("setae %al");
return result; }
|
下面这个改进版,算计编译器会因为看见全局变量,不会对程序结构做什么大改动,但也错了
static int dummy = 0;
int ok_smull(int x, int y, int *dest)
{
int result;
*dest = x*y;
result = dummy;
asm("setae %al");
return result;
}
|
看看下面的汇编代码,先把eax存起来,setae之后,再把eax取回来,所以setae一点用都没有了
__Z8ok_smulliiPi:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl 8(%ebp), %eax
movl %eax, %edx
imull 12(%ebp), %edx
movl 16(%ebp), %eax
movl %edx, (%eax)
movl __ZL5dummy, %eax
movl %eax, -4(%ebp)
/APP
# 9 "ok_smul.cpp" 1
setae %al
# 0 "" 2
/NO_APP
movl -4(%ebp), %eax
leave
ret
|
.......................................................
记录下每一小步,以防忘掉吧
阅读(1086) | 评论(0) | 转发(0) |