私はクラスラボでこれを行っていますが、どこが間違っているのかわかりません。プログラムは、すべての命令にqの代わりにlを接尾辞として付けた場合(たとえば、andqの代わりに-andl、rrmovqの代わりにrrmovl)、qではなく動作します。私が間違っていることについてのいくつかの指針を本当に感謝します。
.pos 0
init: irmovq Stack, %rsp # Set up stack pointer
rrmovq %rsp,%rbp # Set up base pointer
irmovq ele1,%rax
pushq %rax
call sum_list # Execute main program
halt # Terminate program
# Sample linked list
.align 8
ele1: .quad 0x00a
.quad ele2
ele2: .quad 0x0b0
.quad ele3
ele3: .quad 0xc00
.quad 0
# int sum_list(list_ptr ls)
sum_list: pushq %rbp
rrmovq %rsp,%rbp
xorq %rax,%rax # val = 0
mrmovq 8(%rbp),%rdx # edx = ls
andq %rdx,%rdx # Set condition codes
je End
Loop: mrmovq (%rdx),%rcx # ecx = ls->val
addq %rcx,%rax # val += ls->val
mrmovq 4(%rdx),%rdx # ls = ls->next ------ tried +8 insetead of 4 also
andq %rdx,%rdx # Set condition codes
jne Loop
End: rrmovq %rbp,%rsp
popq %rbp
nop # makes sure stop in 31 steps
ret
# The stack starts here and grows to lower addresses
.pos 0x100
スタック:
関数の引数が正しく取得されていないと思います。mrmovq 8(%rbp),%rdx
関数の差出人アドレスをに入れます%rdx
。
それはたまたま数バイト前ですele1
。これは、クラッシュすることなく表示される「シフトされた」値を作成しているオフセット負荷を説明しています。ただし、IDKは、その直後にクラッシュしないようにします。
ポインタ引数は、呼び出し元によってpush %rax
。を使用してスタックに配置されます。その後call
、リターンアドレス(8バイト)をプッシュします。
関数内で、にコピーする前にさらに8バイトpush %rbp
ずつデクリメント%rsp
します%rbp
。したがって、呼び出し元によってプッシュされたポインタ引数はにあり16(%rsp)
、これも16(%rbp)
です。
mrmovq 16(%rbp),%rdx # rdx = ls
デバッグするときは、常に仮定をテストするようにしてください。難しい部分は、あなたが何を想定しているのかを理解することです。なぜなら、それはあなたがあなたを噛む可能性のある問題としてさえ考えていなかったものだからです。(たとえば、この場合、関数argsを取得します。)
64ビットx86コードのように、関数引数をレジスタに渡す方が簡単です。たとえば、最初のarg in %rdi
、2番目のargは、%rsi
x86-64 SystemVの呼び出し規約で使用されているものです。ただし、32ビットx86の呼び出し規約のように、スタックに引数を渡すことが「想定されている」場合push
は、それぞれの幅が8バイトであることを忘れないでください。
OTOH、スタックの使用方法を理解し、スタックに対して呼び出し/プッシュ/ポップが何を行っているかを追跡することが重要です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加