Cとx86-64アセンブリ言語の間にハイブリッドプログラムを作成しようとしています。このプログラムは、Collatz関数を使用して、1と指定されたパラメータnの間の最大停止時間を計算する必要があります。 main関数はC言語で書かれており、for-loopではアセンブリで記述された外部関数を呼び出します。アセンブリ分割エラーのCollatz関数
コンパイルされたハイブリッドプログラムを2より大きい値で実行すると、セグメンテーションフォルトが発生します。gdb再帰呼び出しを行うとエラーが発生しました。
Cコード:これは私が取得していますエラーです
#include <stdio.h>
#include <stdlib.h>
int noOfOp = 0;
extern int collatz(long long n);
// The main function. Main expects one parameter n.
// Then, it computes collatz(1), colllatz(2), ..., collataz(n) and finds the
// a number m, 1 <= m <= n with the maximum stopping time.
int main(int argc, char *argv[]){
if (argc != 2) {
printf("Parameter \"n\" is missing. \n");
return -1;
} else {
int max=0;
long long maxn=0;
int tmp=0;
long long n = atoll(argv[1]);
for (long long i=1 ; i<=n ; i++) {
tmp = collatz(i);
if (tmp > max) {
max = tmp;
maxn=i;
}
}
printf("The largest stopping time between 1 and %lld was %lld ", n,maxn);
printf("with the stopping time of %d. \n", max);
}
}
そして、これは私が書いたx86-64のアセンブリコードです。私はこのコードがアセンブリの適切な理解の欠如を反映していると期待しています。これは、この新しいトピックを完成させるために4日間与えられたクラスの課題です。通常、私はより多くのドキュメントを読んでいたでしょうが、私は単純なのは時間が足りません。アセンブリ言語は難しいです。
.section .text
.global collatz
collatz:
pushq %rbp # save old base pointer
movq %rsp, %rbp # create new base pointer
subq $16, %rsp # local variable space
cmpq $1, %rdi # compare n to 1
je is_one # if n = 1, return noOfOp
incq noOfOp # else n > 1, then increment noOfOp
movq %rdi, %rdx # move n to register rdx
cqto # sign extend rdx:rax
movq $2, %rbx # move 2 to register rbx
idivq %rbx # n/2 -- quotient is in rax, remainder in rdx
cmpq $1, %rdx # compare remainder to 1
je is_odd # if n is odd, jump to is_odd
jl is_even # else n is even, jump to is_even
leave # remake stack
ret # return
is_odd:
movq %rdi, %rdx # move n to register rdx
cqto # sign extend rdx:rax
movq $3, %rbx # move 3 to register rbx
imulq %rbx # n * 3 -- result is in rax:rdx
movq %rax, %rdi # move n to register rdi
incq %rdi # n = n + 1
call collatz # recursive call: collatz(3n+1) <---- this is where the segmentation fault seems to happen
leave # remake stack
ret # return
is_even:
movq %rax, %rdi # n = n/2 (quotient from n/2 is still in rax)
call collatz # recursive call: collatz(n/2) <---- I seem to have gotten the same error here by commenting out most of the stuff in is_odd
leave # remake stack
ret # return
is_one:
movq noOfOp, %rax # set return value to the value of noOfOp variable
leave # remake stack
ret # return
私が得ることができるすべての助けと提案に感謝します。 Iコードを検査からわずか参照
「通常、私はもっと多くのドキュメントを読んだが、時間がないのは簡単だ」 - デバッグを私たちに委託していますか?それはスタックオーバーフローの仕組みではありません!私たちはデバッグサービスではありません。 See [ask]。 – Olaf
デバッガを使用してコードをシングルステップ実行し、終了条件を確認します。なぜそれが止まると思うのか分かりません。時には '2'で割り切っても、' 3n + 1'は無限になります。 PS: 'rbx'は呼び出し先保存レジスタです。 PS#2:2で割るために 'idiv'を使用しています:) PS#3:' imul'と '3'についても同様です。 – Jester
関数が呼び出されたときにCコンパイラの呼び出しインタフェースとは何ですか? 'collatz()'の呼び出しを行う前に引数の値をスタックにプッシュする必要がありますか、それとも 'rdi'というレジスタに渡しますか?私は 'collatz()'関数をC言語で記述し、それをコンパイラを通してプログラム全体を通して実行し、アセンブラ出力を生成し、コンパイラが再帰呼び出しで何をしているのかを確認します。 –