MIPS堆栈帧(和"addiu"指令混乱) [英] MIPS stack frame (and "addiu" instruction confusion)
问题描述
我是MIPS的新手,正在尝试了解函数的反汇编.
(它动态链接到/lib/ld-uClib.so.0并使用一些常用的libc函数,因此我假设它是使用uClibc工具链用C编写的,因此应该具有该调用过程和堆栈框架等).
I'm new to MIPS and am trying to understand the disassembly of a function.
( it is dynamically linked to /lib/ld-uClib.so.0 and uses some usual libc functions, so I assume it was written in C using the uClibc toolchain, and should therefore have that calling procedure and stack frame, etc.).
在函数开始时会执行
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.
Question #1:
Despite searching around for awhile on the internet, I still don't really understand how gp is supposed to be used in the stackframe.
特别是,我读到的文档说调用过程标准是a0-a3用作函数输入,v0-v3用作函数输出,s0-s8保留在所有调用中,t0-t9不在任何调用中保留.因此,推和弹出s0-s8是有意义的. 可是为什么为什么要根据t9中的值设置gp!?
In particular, the documents I read say the call procedure standard is a0-a3 are used as function input, v0-v3 as function output, s0-s8 are preserved across calls, and t0-t9 are not preserved across any call. So the pushing and popping of s0-s8 make sense. But why in the world is it setting gp according to the value in t9!?
问题2:
我不明白为什么它两次移动堆栈指针.它似乎保留了两次本地空间.
Question #2:
I don't understand why it moves the stack pointer twice. It seems to reserve local space twice.
最重要的是,addiu指令被反汇编为负号,这是没有意义的,因为'u'表示无符号,但是除非我实际上认为它是负数.我在en.wikipedia.org/wiki/MIPS_architecture上进行了仔细检查,以检查操作码.它的确是"addiu"而不是"addi".我在这里很困惑.
And on top of that, the addiu instruction is being disassembled with a negative number which doesn't make sense since the 'u' means unsigned, however the code doesn't make sense unless I actually consider it a negative number. I double checked the opcode by looking it up at en.wikipedia.org/wiki/MIPS_architecture. And it is indeed "addiu" and not "addi". I'm so confused here.
推荐答案
前三个说明用于支持位置独立代码.请参阅此linux-mips页面,以获取有关MIPS上PIC的详细说明. t9
保留函数的地址,每次加载支持PIC的库时,该地址就可以更改,并且该值将添加到gp
中已经存在的常量中.类似于x86:
The first three instructions are for supporting Position Independent Code. See this linux-mips page for an excellent explanation of PIC on MIPS. t9
holds the address of the function, which can change every time you load a library supporting PIC, and that value is added to a constant already in gp
. Similar to x86's:
call __i686.get_pc_thunk.bx
add $0x1b88, %ebx
__i686.get_pc_thunk.bx
将下一条指令的地址装入%ebx
的位置,随后的加法运算将%ebx
转换为将用于访问全局符号的参考点.
Where __i686.get_pc_thunk.bx
loads %ebx
with the address of the next instruction, and the subsequent add converts %ebx
into a point of reference that will be used to access global symbols.
ADDIU:
在MIPS上,有符号加法和无符号加法之间的唯一区别是,有符号加法会引发溢出异常,因此使用ADDIU
可以避免这种情况.
ADDIU:
The only difference between signed and unsigned addition on MIPS is that signed addition can raise an overflow exception, so ADDIU
is used instead to avoid that.
多次堆栈调整:这些可能与MIPS使用16位立即数的事实有关,因此不能始终在一个ADDIU
中调整堆栈.
Several stack adjustments: These probably relate to the fact that MIPS uses 16-bit immediates, so cannot always adjust the stack in one ADDIU
.
这篇关于MIPS堆栈帧(和"addiu"指令混乱)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!