コードには複数の問題があります。
From64bit Ubuntu
とpushq %rax
私はあなたが64ビットの実行可能ファイルを作ろうとしていると推測します。
その場合は、...
ここ:
pushq %rax
pushq $output
call printf
addl $8, %esp
関数呼び出し後にスタックのバランスが適切に取れていません。これが64ビットコードであることを今でも覚えていますか?に追加する必要があります。rsp
ではなく、に追加する必要がありesp
ます。また、2つの8バイトパラメータをプッシュする場合は、正確に2つの8バイトパラメータを削除する必要があります。つまり、8ではなく16を追加する必要があります。
しかし、それよりもさらに悪いです。64ビットモードでは、パラメータの受け渡しが異なります。rdi
最初のパラメータは、レジスタ、、、、、およびにrsi
あります。だから、それは私たちに与えます:rdx
rcx
r8
r9
movq %rax, %rsi
movq $output, %rdi
movq $0, %rax ; number of vector registers used for var-arg-function printf()
call printf
ここ:
inc %edi
rdi
呼び出しによって、およびこのレジスタをパラメータの受け渡しに使用することにより、の値を破棄しました。rdi
呼び出しの前に手動でプッシュしてから、ポップバックする必要があります。または、グローバル変数に保存することもできます。プッシュアンドポップを選択する場合は、命令rsp
の前にスタックポインタが常に16バイト整列されていることを確認してください。call
ここ:
movl $0, %ebx
movl $1, %eax
int $0x80
32ビットのシステムコールインターフェイスを使用しています。64ビットプログラムでは、64ビットシステムコールインターフェイスを使用する必要があります。
movq $60, %rax ; sys_exit
movq $0, rdi ; return 0 (success)
syscall
さて、これにも問題があると思います。
movl $0, %edi
loop :
movl values( , %edi, 4), %eax
一般に、64ビットコードのアドレス計算では、32ビットレジスタと32ビット命令を使用しないでください。私はそれを次のように変更します:
movl $0, %rdi
loop :
movl values( , %rdi, 4), %eax
のアドレスがvalues
2GB以上離れているために、2つのどちらも機能しない場合rip
(事実:変位は、64ビットモードのほとんどの命令でメモリオペランドの32ビット符号付き整数に制限され、ほとんどの命令には変位のみのメモリオペランドがありません64ビットモードでエンコードする場合は、rip
-relative addressingを使用します)、64ビットアドレスvalues
とインデックスを手動で追加し、4を掛けた配列にインデックスを追加する必要があります。切り捨てなしで64ビット追加を行うようにしてください。途中で。
必読: