/*************************018.c 综合实例************************
* C 语言编程百例的第18个例子:
* 验证哥德巴赫猜想,即任一充分大的偶数,可以用2个素数之和表示
*/
#include<math.h>
#include<stdio.h>
void main()
{
int i,j,num;
int p,q,flagp,flagq;
printf("Please input a plus integer:");
scanf("%d",&num);
//代码(num%2)!=0 表示 num不能被2整除
if(((num%2)!=0)||(num<=4))
printf("input data error!\n");
else
{
p=1;
do
{
p=p+1;
q=num-p;
flagp=1;
flagq=1;
for(i=2;i<=(int)(floor(sqrt((double)(p))));i++)
{
if((p%i)==0)
{
flagp=0;
break;
}
}
if (flagp==0) continue;//教材里没有词句,自己加的
j=2;
while(j<=(int)(floor(sqrt((double)(q)))))
{
if((q%j)==0)
{
flagq=0;
break;
}
j++;
}
}while ((flagp*flagq)==0);
printf("%d=%d+%d\n",num,p,q);
}
}
对应的汇编
.file "018.c"
.def ___main; .scl 2; .type 32; .endef
.text
LC0:
.ascii "Please input a plus integer:\0"
LC1:
.ascii "%d\0"
LC2:
.ascii "input data error!\12\0"
LC3:
.ascii "%d=%d+%d\12\0"
.align 2
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $56, %esp
andl $-16, %esp # 没有找到堆栈对界的相关资料,-16是FFFFFFF0;
movl $0, %eax
movl %eax, -40(%ebp)
movl -40(%ebp), %eax
call __alloca
call ___main
subl $12, %esp # 给printf做准备,但为什么?
pushl $LC0 # "Please input a plus integer:\0" 入栈 esp-4
call _printf # 调用printf, esp未发生变化
addl $16, %esp # 平衡堆栈,栈空间回到printf前的状态
subl $8, %esp # 为scanf("%d",&num)准备
leal -12(%ebp), %eax
pushl %eax
pushl $LC1
call _scanf
addl $16, %esp
movl -12(%ebp), %eax # eax =num
andl $1, %eax # eax 前31位清零
testl %eax, %eax # 测试eax第一位是否为1
jne L35 # 这里可以修改为jnz, 如果为1就是奇数,则跳转
cmpl $4, -12(%ebp) # 比较 num 和 4
jle L35 # <= 跳转
jmp L34
L35:
subl $12, %esp # printf("input data error!\n");
pushl $LC2
call _printf
addl $16, %esp
jmp L33 # 退出程序
L34:
movl $1, -16(%ebp) # p=1
L37:
leal -16(%ebp), %eax # eax = &p
incl (%eax) # p++
movl -16(%ebp), %edx # edx = p
movl -12(%ebp), %eax # eax = num
subl %edx, %eax # eax = num-p
movl %eax, -20(%ebp) # q = eax
movl $1, -24(%ebp) # flagp=1
movl $1, -28(%ebp) # flagq=1
movl $2, -4(%ebp) # i=2
L40:
subl $8, %esp # 调整栈,调用sqrt((double)(p))
fildl -16(%ebp) # 加载p到st0
leal -8(%esp), %esp # esp 指向 -8(%esp)
fstpl (%esp) # 数据保存到栈顶(%esp)
call _sqrt # 调用sqrt((double)(p)),
addl $8, %esp # 平衡堆栈;
leal -8(%esp), %esp # 准备调用floor
fstpl (%esp) # 参数入栈
call _floor # 调用floor
addl $16, %esp # 平衡堆栈;
fnstcw -30(%ebp) # 把控制寄存器的内容存储到-30(%ebp)
movw -30(%ebp), %ax # 控制寄存器内容入ax
movb $12, %ah # 控制内容处理;具体怎么处理没搞清楚
movw %ax, -32(%ebp)
fldcw -32(%ebp) # 设置控制寄存器
fistpl -36(%ebp) # 浮点数转化为整数
fldcw -30(%ebp) # 设置控制寄存器
movl -36(%ebp), %eax # eax=(int)(floor(sqrt((double)(p))))的运算结果
cmpl %eax, -4(%ebp) # 比较i和eax
jle L43 # i<=eax 跳,执行循环内容
jmp L41 # 循环结束
L43:
movl -16(%ebp), %edx # edx=p
movl %edx, %eax # eax = edx
sarl $31, %edx # edx 右移31位
idivl -4(%ebp) # p/i eax存商,edx存余数
testl %edx, %edx # 判断p%i是否为0
jne L42
movl $0, -24(%ebp) # flagp=0;
jmp L41
L42:
leal -4(%ebp), %eax # i++
incl (%eax) #
jmp L40
L41:
cmpl $0, -24(%ebp) # 判断flagp==0
jne L45 # 不等于0,继续进行
jmp L39 # 否则,判断循环条件,进行下一循环。
L45:
movl $2, -8(%ebp)
L46:
subl $8, %esp
fildl -20(%ebp)
leal -8(%esp), %esp
fstpl (%esp)
call _sqrt
addl $8, %esp
leal -8(%esp), %esp
fstpl (%esp)
call _floor
addl $16, %esp
fnstcw -30(%ebp)
movw -30(%ebp), %ax
movb $12, %ah
movw %ax, -32(%ebp)
fldcw -32(%ebp)
fistpl -36(%ebp)
fldcw -30(%ebp)
movl -36(%ebp), %eax
cmpl %eax, -8(%ebp)
jle L48
jmp L39
L48:
movl -20(%ebp), %edx
movl %edx, %eax
sarl $31, %edx
idivl -8(%ebp)
testl %edx, %edx
jne L49
movl $0, -28(%ebp)
jmp L39
L49:
leal -8(%ebp), %eax
incl (%eax)
jmp L46
L39:
movl -24(%ebp), %eax
imull -28(%ebp), %eax
testl %eax, %eax
je L37
pushl -20(%ebp)
pushl -16(%ebp)
pushl -12(%ebp)
pushl $LC3
call _printf
addl $16, %esp
L33:
leave
ret
.def _sqrt; .scl 2; .type 32; .endef
.def _floor; .scl 2; .type 32; .endef
.def _scanf; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef