汇编实验4(99乘法表,整数分解,素数环,迷宫问题)【栈传参,递归,寻址方式】

目录

一、99乘法表

汇编代码

效果

二、整数拆分

问题描述

c代码

汇编代码

效果

三、素数环

问题描述

c代码

效果

四、迷宫问题

问题描述

c代码

汇编代码

效果


一、99乘法表

汇编代码

INCLUDE Irvine32.inc
.data
a db '*',0
.code
main PROC
mov ebx,1;ebx=i
mov ecx,1;ecx=j
l0:
cmp ebx,9
ja final
mov ecx,1
l2:
cmp ecx,ebx
ja l1
mov eax,ebx
call writedec
mov al,a
call writechar
mov eax,ecx
call writedec
mov al,' '
call writechar
call writechar
inc ecx
jmp l2
l1:
call crlf
inc ebx
jmp l0
final:
	 exit
main ENDP
end main

#include <stdio.h>
int main(){
    int i,j;
    for(i=1;i<=9;i++)
    {
        for(j=1;j<=i;j++)
            {printf("%d*%d=%2d  ",i,j,i*j);}
        printf("\n");
    }

    return 0;
}

效果

貌似有点问题,忘了把运算结果加上......

二、整数拆分

问题描述

问题描述
输入一个N,输出所有拆分的方式。
如input: 3
output: 
1+1+1
1+2
3

算法思想
用一个数组res[]存放拆分的解,用全局变量存放拆分的方法数。
divN(n,k)使用n表示要分解的整数,k表示res数组下标,即第k次拆分。
先从divN(n,1)开始,用num表示第k个拆分的数,即res[k]=num,
让num在[1,n]内遍历。用rest=n-num表示拆分后剩下的整数值。若rest等于零,
代表本次拆分结束,输出拆分解。否则处理第k+1个数组元素,即divN(rest,k+1),
依次类推,直到rest为0输出结果。

c代码

#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
int res[10000] = { 0 }; //res数组存放解
int times = 0; //times计算拆分的次数
void divN(int n, int k) { //n是需要拆分的整数,k是指res数组的下标
    int rest; //存放拆分后剩余的整数
    for (int num = 1;num <= n; num++) {  //从1开始尝试拆分
         if (num >= res[k - 1] ) { //拆分的解要大于或等于前一个解保证不重复
            res[k] = num; //将这次拆分存放在res数组中
            rest = n - num; //剩下的是n-num
            if (rest == 0) { //如果没有剩下的,说明本次拆分结束
                times++;  //拆分次数加1
		printf("%3d:", times);
                for (int j = 1; j < k; j++) {  //输出解
                    printf("%d+", res[j]);
                }
                printf("%d\n", res[k]);
            }
            else divN(rest, k + 1);  //如果有剩下的,继续求出res[k+1]
        }
    }
}
int main() {
    int n;
    printf("Please enter a integer N:");
    scanf_s("%d", &n);
    divN(n, 1);
    printf("there are %d ways to divide the integer %d.", times,n);
    system("pause");
    return 0;
}

汇编代码

INCLUDE Irvine32.inc
.data
res dd 10000 dup(0)
times dd 0
n dd ?
st1 db 'Please enter a integer N:',0
.code
main PROC
mov edx,offset st1
call writestring
call readint
mov n,eax
push n
push 1
call divN
exit
main ENDP

divN PROC
push ebp
mov ebp,esp
pushad
mov ecx,[ebp+8];ecx=k
mov edx,[ebp+12];edx=n
               ;edi=rest
mov ebx,1;ebx=num
l0:;for
cmp ebx,edx
ja final
mov eax,ebx;eax=ebx
cmp eax,res[4*ecx-4]
jl l1
mov res[4*ecx],eax
mov eax,edx
sub eax,ebx;eax=n-ebx
mov edi,eax
cmp edi,0
jnz l2
inc times
mov eax,times
call writedec
mov al,' '
call writechar
mov esi,1;esi=j
l3:;for
cmp esi,ecx
jae l4
mov eax,res[+4*esi]
call writedec
mov al,'+'
call writechar
inc esi
jmp l3
l4:
mov eax,res[4*ecx]
call writedec
call crlf
jmp l1
l2:;else
push edi
mov eax,ecx
inc eax;eax=k+1
push eax
call divN
l1:
inc ebx
jmp l0
final:
popad
pop ebp
ret 8
divN ENDP
END main

效果

 

三、素数环

问题描述

素数环

题目:输入正整数n,把整数1,2,3,...,n组成一个环。
使得相邻两个整数之和均为素数。

输出时从整数1開始逆时针排列。

同一个环应该恰好输出一次。

c代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn =1000;
int vis[maxn];
int A[maxn];
int isp[maxn];
int n;
int ans=0;

int is_prime(int x){
    for( int i=2; i*i<=x; i++ ){
        if(x%i==0) return 0;
    }
    return 1;
}

void dfs(int cur){
    if(cur==n&&isp[A[0]+A[n-1]]){
        ans++;
        for( int i=0; i<n; i++ ) cout<<A[i]<<" ";
        cout<<endl;
    }
    else{
        for(int i=2; i<=n; i++ ){
            if(!vis[i]&&isp[i+A[cur-1]]){
	       /*i这个数没被用过,并且符合前后两个数相加为素数的要求*/
                A[cur]=i;/*采用这个数*/
                vis[i]=1;/*设置使用标志*/
                dfs(cur+1);
                vis[i]=0;/*消除标志*//*回溯的本质*/
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    cin>>n;
    memset(vis,0,sizeof(vis));
    for( int i=2; i<=n*2; i++ ) isp[i]=is_prime(i);
    A[0]=1;/*题目中规定从1开始*/
    dfs(1);
    cout<<ans<<endl;

    return 0;
}

汇编代码

INCLUDE Irvine32.inc
.data
ans dd 0
vis dd 1000 dup(0)
A dd 1000 dup(?)
isp dd 1000 dup(?)
n dd ?
.code
main PROC
mov ecx,offset A
mov eax,1
mov [ecx],eax
mov eax,0
call readint
mov n,eax
mov ebx,2;ebx=i
l0:
mov eax,n
add eax,eax;eax=2*n
cmp ebx,eax
ja l1
push ebx
call is_prime
mov ecx,offset isp;ecx=isp
mov [ecx+4*ebx],eax
inc ebx
jmp l0
l1:
push 1
call dfs
mov eax,ans
call writedec
call crlf
exit
main ENDP

is_prime PROC
push ebp
mov ebp,esp
sub esp,4
pushad
mov ebx,[ebp+8];ebx=x
mov ecx,2;ecx=i
mov eax,0
mov [ebp-4],eax
l0:
mov eax,ecx
mul ecx
cmp eax,ebx
ja final1
mov edx,0
mov eax,ebx
div ecx
cmp edx,0
je final2
inc ecx
jmp l0
final1:
mov eax,1
mov [ebp-4],eax
final2:
popad
mov eax,[ebp-4]
add esp,4
pop ebp
ret 4
is_prime ENDP

dfs PROC
push ebp
mov ebp,esp
pushad
mov ebx,[ebp+8];ebx=cur
mov ecx,offset A;ecx=A
mov esi,offset isp;esi=isp
mov edi,offset vis;edi=vis
cmp ebx,n
jne l0
mov eax,[ecx]
mov esi,n
add eax,[ecx+esi*4-4];eax=A[0]+A[n-1]
mov esi,offset isp;esi=isp
mov eax,[esi+eax*4];eax=isp[A[0]+A[n-1]]
cmp eax,1
jne l0
inc ans
mov edx,0;edx=i
l1:
cmp edx,n
jae l2
mov eax,[ecx+edx*4]
call writedec
mov al,' '
call writechar
inc edx
jmp l1
l2:
call crlf
jmp final

l0: ;else
mov edx,2;edx=i
l3: ;for
cmp edx,n
ja final
mov eax,1
cmp [edi+4*edx],eax
je l4
mov eax,ebx
dec eax;eax=cur-1
mov eax,[ecx+4*eax]
add eax,edx
mov eax,[esi+4*eax]
cmp eax,1
jne l4
mov [ecx+ebx*4],edx
mov eax,1
mov [edi+edx*4],eax
mov eax,ebx
inc eax;eax=cur+1
push eax
call dfs
mov eax,0
mov [edi+4*edx],eax
l4:
inc edx
jmp l3
final:
popad
pop ebp
ret 4
dfs ENDP
END main

效果

四、迷宫问题

问题描述

有一个 7 x 7 的迷宫,起点是'S',终点是'E',墙是'o',道路是空格。
请找出从起点到终点的通路,通路用符号'.'表示。


用二维数组表示迷宫场景。其中用2代表迷宫的墙壁,0代表可行通道。
走的路径记作1,也就是数组中的0被改为1

c代码

#include <stdio.h>
#include <stdlib.h>
#define M 9
//把7*7迷宫加大成9*9格局
int maze[M][M] ={
        {2,2,2,2,2,2,2,2,2},
        {2,0,0,0,0,0,0,0,2},
        {2,0,2,2,0,2,2,0,2},
        {2,0,2,0,0,2,0,0,2},
        {2,0,2,0,2,0,2,0,2},
        {2,0,0,0,0,0,2,0,2},
        {2,2,0,2,2,0,2,2,2},
        {2,0,0,0,0,0,0,0,2},
        {2,2,2,2,2,2,2,2,2}
};

int start1=1,start2=1;          //假定[1][1]是入口
int end1=7,  end2=7;            //假定[7][7]是出口

void visit(int i,int j){
        int m,n;
	maze[i][j] = 1;
        if(i==end1 && j==end2) { //判断是否到达出口位置,到达直接输出
             printf("\n显示路径:\n");
             for(m=0;m<M;m++){
                 for(n=0;n<M;n++){
                     if(maze[m][n] == 2)  printf("o");
                     else if(maze[m][n] == 1)  printf(".");
                     else     printf(" ");						
                  }
                  printf("\n");
              }//end for
	 }//end if

        //不再判定是否到达出口,只分析老鼠可以在迷宫移动的方向,
	//并递归求下一步.
        if(maze[i][j+1] == 0)    visit(i,j+1);
        if(maze[i+1][j] == 0)    visit(i+1,j);
        if(maze[i][j-1] == 0)    visit(i,j-1);
        if(maze[i-1][j] == 0)    visit(i-1,j);
	//若代码运行到这一步,则证明前面走的路径并不能到达出口,
	//则返回,把走过的位置重新写作0
        maze[i][j] = 0;
}

int main (){
       int i,j;
       printf("显示迷宫:\n");
       for(i=0;i<M;i++)   {  /对摆放的数组迷宫进行打印
           for(j=0;j<M;j++)
              if(maze[i][j] == 2)   printf("o");
              else    printf(" ");
              printf("\n");
       }
       visit(start1,start2);  //直接调用visit函数,把输出内容放在visit函数中,
	//好让所有路径进行遍历

       return 0;
}

汇编代码

INCLUDE Irvine32.inc
.data
ar dd 2,2,2,2,2,2,2,2,2
   dd 2,0,0,0,0,0,0,0,2
   dd 2,0,2,2,0,2,2,0,2
   dd 2,0,2,0,0,2,0,0,2
   dd 2,0,2,0,2,0,2,0,2
   dd 2,0,0,0,0,0,2,0,2
   dd 2,2,0,2,2,0,2,2,2
   dd 2,0,0,0,0,0,0,0,2
   dd 2,2,2,2,2,2,2,2,2
st1 db '显示迷宫:',0
M dd 9
num dd 36
start1 dd 1
start2 dd 1
end1 dd 7
end2 dd 7
.code
main PROC
mov ebx,0;ebx=i
l0:
cmp ebx,M
jae l1
mov ecx,0;ecx=j
l3:
cmp ecx,M
jae l2
push ecx
push ebx
call find
cmp eax,2
jnz l4
mov al,'o'
call writechar
jmp l5
l4:;else
mov al,' '
call writechar
l5:
inc ecx
jmp l3
l2:
call crlf
inc ebx
jmp l0
l1:
push start1
push start2
call visit
final:
   exit
main ENDP


visit PROC
;push i,push j
push ebp
mov ebp,esp
pushad
mov ebx,[ebp+8] ;ebx=j
mov ecx,[ebp+12];ecx=i
                ;edx=m
                ;esi=n
push 1
push ebx
push ecx
call wri
cmp ecx,end1
jne l0
cmp ebx,end2
jne l0
mov edx,0
l1:;for
cmp edx,M
jae l0
mov esi,0
l3:;for2
cmp esi,M
jae l2
push esi
push edx
call find
cmp eax,2
jnz l5
mov al,'o'
call writechar
jmp l4
l5:
cmp eax,1
jnz l6
mov al,'.'
call writechar
jmp l4
l6:
mov al,' '
call writechar
l4:
inc esi
jmp l3
l2:
call crlf
inc edx
jmp l1
l0:;end if
mov eax,ebx
inc eax
push eax
push ecx
call find
cmp eax,0
jne f1
mov eax,ebx
inc eax
push ecx
push eax
call visit
f1:
push ebx
mov eax,ecx
inc eax
push eax
call find
cmp eax,0
jne f2
mov eax,ecx
inc eax
push eax
push ebx
call visit
f2:
mov eax,ebx
dec eax
push eax
push ecx
call find
cmp eax,0
jne f3
mov eax,ebx
dec eax
push ecx
push eax
call visit
f3:
push ebx
mov eax,ecx
dec eax
push eax
call find
cmp eax,0
jne f4
mov eax,ecx
dec eax
push eax
push ebx
call visit
f4:
push 0
push ebx
push ecx
call wri
final:
popad
pop ebp
ret 8
visit ENDP

find PROC
;ar[i][j]
;push j,push i
push ebp
mov ebp,esp
sub esp,4
pushad
mov ebx,[ebp+8];ebx=i
mov ecx,[ebp+12];ecx=j
mov eax,ebx
mul num
mov eax,ar[eax+ecx*4]
mov [ebp-4],eax
popad
mov eax,[ebp-4]
add esp,4
pop ebp
ret 8
find ENDP

wri PROC
;n,ar[i][j]
;push n,push j,push i
push ebp
mov ebp,esp
pushad
mov ebx,[ebp+8];ebx=i
mov ecx,[ebp+12];ecx=j
mov edi,[ebp+16];edi=n
mov eax,ebx
mul num
mov ar[eax+ecx*4],edi
popad
pop ebp
ret 12
wri ENDP
END main

效果

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coleak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值