018 综合实例

/*************************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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值