1

私はMIPSを初めて使用し、関数の分解を理解しようとしています。
(編集:/lib/ld-uClib.so.0に動的にリンクされ、通常のlibc関数を使用するため、uClibcツールチェーンを使用してCで記述されていると想定します。したがって、呼び出し元のプロシージャとスタックフレームなどが必要です。 。)。

関数の開始時にそれは行います

00400824 <practice_crackme>:
  400824:   3c1c0fc0    lui gp,0xfc0        ; ???
  400828:   279c673c    addiu   gp,gp,26428 ; ???
  40082c:   0399e021    addu    gp,gp,t9    ; ???

  400830:   27bd8020    addiu   sp,sp,-32736  ; sp -= 0x7fe0 (-32736=0xffff8020)
  400834:   34038670    li  v1,0x8670
  400838:   afbf7fdc    sw  ra,32732(sp)
  40083c:   afbe7fd8    sw  s8,32728(sp)
  400840:   afb77fd4    sw  s7,32724(sp)
  400844:   afb67fd0    sw  s6,32720(sp)
  400848:   afb57fcc    sw  s5,32716(sp)
  40084c:   afb47fc8    sw  s4,32712(sp)
  400850:   afb37fc4    sw  s3,32708(sp)
  400854:   afb27fc0    sw  s2,32704(sp)
  400858:   afb17fbc    sw  s1,32700(sp)
  40085c:   afb07fb8    sw  s0,32696(sp)
  400860:   03a3e823    subu    sp,sp,v1  ; sp-=0x8670 (local space=0x8670 bytes)
  400864:   afbc0018    sw  gp,24(sp)

次に、関数の最後に次のことを行います。

  4009e0:   8fbc0018    lw  gp,24(sp)
  4009e4:   34088670    li  t0,0x8670
  4009e8:   03a8e821    addu    sp,sp,t0    ; sp+=0x8670; //remove local space
  4009ec:   8fbf7fdc    lw  ra,32732(sp)
  4009f0:   8fbe7fd8    lw  s8,32728(sp)
  4009f4:   8fb77fd4    lw  s7,32724(sp)
  4009f8:   8fb67fd0    lw  s6,32720(sp)
  4009fc:   8fb57fcc    lw  s5,32716(sp)
  400a00:   8fb47fc8    lw  s4,32712(sp)
  400a04:   8fb37fc4    lw  s3,32708(sp)
  400a08:   8fb27fc0    lw  s2,32704(sp)
  400a0c:   8fb17fbc    lw  s1,32700(sp)
  400a10:   8fb07fb8    lw  s0,32696(sp)
  400a14:   03e00008    jr  ra
  400a18:   27bd7fe0    addiu   sp,sp,32736 ; sp += 0x7fe0

質問1:
インターネットでしばらく検索しているにもかかわらず、スタックフレームでgpがどのように使用されるのかまだよくわかりません。

特に、私が読んだ文書によると、呼び出し手順の標準は、関数入力としてa0-a3が使用され、関数出力としてv0-v3が使用され、s0-s8は呼び出し全体で保持され、t0-t9はどの呼び出しでも保持されません。したがって、s0-s8のプッシュとポップは理にかなっています。 しかし、なぜ世界でt9の値に従ってgpを設定しているのですか?

質問2:
スタックポインタが2回移動する理由がわかりません。ローカルスペースを2回予約しているようです。

その上、addiu命令はの数で分解されています。これは、「u」が符号なしを意味するため意味がありませんが、実際に負の数と見なさない限り、コードは意味がありません。en.wikipedia.org/wiki/MIPS_architectureでオペコードを調べて、オペコードを再確認しました。そして、それは確かに「addiu」であり、「addi」ではありません。私はここでとても混乱しています。

4

1 に答える 1

2

最初の3つの手順は、位置独立コードをサポートするためのものです。MIPSでのPICの優れた説明については、このlinux-mipsページを参照してください。t9関数のアドレスを保持します。これは、PICをサポートするライブラリをロードするたびに変更される可能性があり、その値はすでににある定数に追加されgpます。x86と同様:

call __i686.get_pc_thunk.bx
add $0x1b88, %ebx

ここで、次の命令のアドレスが__i686.get_pc_thunk.bxロードされ、後続のaddは、グローバルシンボルにアクセスするために使用される参照ポイントに変換されます。%ebx%ebx

ADDIU: MIPSでの符号付き加算と符号なし加算の唯一の違いは、符号付き加算はオーバーフロー例外を発生させる可能性があるため、それADDIUを回避するために代わりに使用されます。

いくつかのスタック調整:これらはおそらく、MIPSが16ビットのイミディエートを使用するという事実に関連しているため、常に1つのスタックを調整できるとは限りませんADDIU

于 2011-07-26T20:33:39.487 に答える