私は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」ではありません。私はここでとても混乱しています。