8


2

x86-64関数のプリアンブルを理解できない

クラッシュが発生しており、調査中に次のコードによって完全にブロックされていることがわかりました。

0000000000000a00 <_IO_vfprintf>:
a00:       55                      push   %rbp
a01:       48 89 e5                mov    %rsp,%rbp
a04:       41 57                   push   %r15
a06:       41 56                   push   %r14
a08:       41 55                   push   %r13
a0a:       41 54                   push   %r12
a0c:       53                      push   %rbx
a0d:       48 81 ec 48 06 00 00    sub    $0x648,%rsp
a14:       48 89 95 98 f9 ff ff    mov    %rdx,0xfffffffffffff998(%rbp)

これは、64ビットLinux x86システムで `objdump --disassemble / usr / lib64 / libc.a`を実行し、出力を検索することで生成されます。 これはhttp://en.wikipedia.org/wiki/X86_assembly_language#Syntax[AT&T構文]であるため、宛先は右側にあります。

具体的には、私は最後の命令を理解していません。 関数がそのレジスタに触れる前に、スタックのどこか(遠く、遠く)のメモリに `rdx`レジスタの値を書き込んでいるようです。 私には、これは何の意味もありません。

私は呼び出し規約を読んでみましたが、今の私の最良の理論は、パラメーターに `rdx`が使用されているため、コードは基本的にパラメーター値を直接「返す」ことです。 これは関数の終わりではないので、もちろん実際には戻りません。

1 Answer


12


はい、それはパラメータです。 Linuxで使用されるABIは、最大6個の「整数」(⇐ 64ビット整数、またはポインター)型パラメーターをレジスターに割り当てます。そして、覚えやすい順序「%rdi」、「%rsi」、「%rdx」、「%rcx」、「%r8」、「%r9」。

スタックフレームは1648バイト(「sub $ 0x648、%rsp」は1608バイトに加えて、その前に5つの64ビットレジスタがプッシュされている)、「0xfffffffffffff998」は-1640です。

そのため、コードは3番目のパラメーターをスタックフレームの下部近くに格納しています。

(注:Windows 64ビットABIはLinuxのものとは異なります。)