ハミルトニアンループアセンブリ言語実装(小さなバグあり)

13763 ワード

C++  
#include #include #include /* , , , , , n , */ int graph[30][30]; int sign[30]; int n,m,ans=0; void DFS(int now,int step); int main() { int u,v; scanf("%d %d",&n,&m); // 1 for(int i=0;i){ scanf("%d %d",&u,&v); graph[u][v]=graph[v][u]=1; } sign[1]=1; DFS(1,1); printf("%d
",ans); return 0; } void DFS(int now,int step){ if(step==n){ if(graph[1][now]){ ans=1; } return; } for(int i=1;i<=n;i++){ if(!sign[i] && i!=now && graph[now][i]){ sign[i]=1; DFS (i,step+1); sign[i]=0; } } return; }
    :(  bug,           ,            )

.macro done li $v0,
10 syscall .end_macro ############################################################# .macro initial li $t0,0 for_1: beq $t0,$s0,for_1_end sll $t1,$t0,2 #t1=t0*4(int is 4 byte) add $t1,$t1,$s3 sw $0,0($t1) #sign[t1]=0 addi $t0,$t0,1 #t0=t0+1 j for_1 for_1_end: .end_macro ############################################################# .macro getindex(%ans,%i,%j) mult %i,$t6 #i*10 mflo $t4 #t4=i*10 add %ans,$t4,%j #t4=i*10+j sll %ans,%ans,2 #ans=ans*4 .end_macro ############################################################# .data matrix: .space 400 sign: .space 40 ######################################################### .text main: la $s2,matrix la $s3,sign li $t6,10 #tmp li $t7,1 #tmp li $s7,0 #s7 is answer li $v0,5 syscall move $s0,$v0 #s0 is n li $v0,5 syscall move $s1,$v0 #s1 is m initial li $t0,0 #t0 is i for_create: beq $t0,$s1,for_create_end #if i==m,stop add edge li $v0,5 syscall move $t1,$v0 #t1 is u li $v0,5 syscall move $t2,$v0 #t2 is v getindex($t3,$t1,$t2) #get the address in matrix add $t3,$t3,$s2 #get address in matrix,t3 is address sw $t7,0($t3) #add edge (u,v) getindex($t3,$t2,$t1) add $t3,$t3,$s2 sw $t7,0($t3) #add edge (v,u) addi $t0,$t0,1 #i++ j for_create for_create_end: sw $t7,4($s3) #sign[1]=1 li $a0,1 #a0 is now position li $a1,1 #a1 is step jal dfs #the return address is in $31 li $v0,1 li $a0,0 syscall done dfs: sw $31,0($sp) addi $sp,$sp,-4 blt $a1,$s0,dfs_else getindex($t3,$t7,$a0) add $t3,$t3,$s2 #t3 is address in matrix lw $t4,0($t3) #t4=graph[1][now] beq $t4,1,arrive_ans addi $sp,$sp,4 lw $31,0($sp) jr $31 #if we don't find the ans,return #omit something………… dfs_else: jal dfs_work addi $sp,$sp,4 lw $31,0($sp) jr $31 then: jr $31 #you have jumped to main succesfully arrive_ans: li $s7,1 li $a0,1 li $v0,1 #print answer syscall done j then dfs_work: #then ,we should do something li $t0,1 #t0 is i sw $31,0($sp) #save return address addi $sp,$sp,-4 for_dfs1: bgt $t0,$s0,for_dfs1_end bge $a1,$s0,for_dfs1_end sw $a0,0($sp) #save now addi $sp,$sp,-4 sw $a1,0($sp) #save step addi $sp,$sp,-4 #all the info was saved sucessfully sll $t1,$t0,2 #t1=t0*4 add $t1,$t1,$s3 #t1 is the address in array_sign lw $t2,0($t1) #t2 is sign[i] getindex($t3,$a0,$t0) #t3 is [now][i] lw $t3,0($t3) #t3 is graph[now][i] beq $t2,1,else #if sign[i]==1,return beq $t0,$a0,else #if i==now,return beq $t3,0,else #if graph[now][i]==0,return sw $t7,0($t1) #sign[i]=1; sw $t0,0($sp) #save tmpi in stack addi $sp,$sp,-4 sw $t1,0($sp) #save the address in array_sign addi $sp,$sp,-4 move $a0,$t0 #now=i addi $a1,$a1,1 #step++ jal dfs #next recursion addi $sp,$sp,4 lw $t1,0($sp) #fetch the address in array_sign addi $sp,$sp,4 lw $t0,0($sp) #fetch i sw $t7,0($t1) #sign[i]=0 addi $sp,$sp,4 lw $a1,0($sp) addi $sp,$sp,4 lw $a0,0($sp) #fetch all the things addi $t0,$t0,1 #i++ j for_dfs1 for_dfs1_end: addi $sp,$sp,4 lw $31,0($sp) #fetch the leeway jr $31 else: addi $t0,$t0,1 addi $sp,$sp,4 lw $a1,0($sp) addi $sp,$sp,4 lw $a0,0($sp) #fetch all the things j for_dfs1

 
アセンブリ言語で再帰プログラムを書く経験と教訓:
1.値のインスタックとアウトスタック:これは必ず注意して、他のプロセスを呼び出すたびに、退路を保存するかどうかを考えて、元の変数を保存して、一度だけ保存していないものもあれば、分岐のために各分岐の中でスタックをアウトにしなければならないものもあります.再帰的にはもっと練習しなければなりませんが、今回は6時間も書いたのに1ポイントも引っかかってしまったので、私のP 2はたぶんやられることになります.
2.判断条件の書き方:等しい判断でbeqが足りない場合が多い(自分で書いたプログラムがあまりにも混乱しているため、値が予想以上になる)と判断するには、等しい、小さい、厳格で小さい、厳格で大きい命令を判断する必要があります.どちらを使うかは、必ずコードを書くときに考えなければなりません.ループ終了の条件は一般的にループの一番前に書かれています.各条件判断の後にはっきりした注釈を書いたほうがいいです.
[原句]怖がらないで.アセンブリプログラムは長いのを見ていますが、実際に重複している部分はスタックに入ってスタックを出ていることが多いので、後で書くときは気が狂って物を壊すことはできません.