ARM处理器:堆栈内容

时间:2014-08-12 16:15:17

标签: assembly gdb arm objdump

我正在尝试分析ARM二进制文件的objdump。

我看到在我的情况下局部变量的数量是2个整数,每个整数大小为4个字节。该功能没有参数。我希望函数将堆栈指针递减8,但堆栈指针递减16。

这在我的测试集中的所有函数中都会发生。

有人可以帮我理解发生了什么吗?或者指出一些我可以理解的文件。

编辑: 它是32位ARM 11处理器,如果有帮助的话。

此外,函数参数正在寄存器中发送。

从我的小测试集中,我发现SP的值比局部变量的大小增加了8倍。

EDIT2:

这是一些代码。

Objdump

    0000036c <adpcm_coder>:
 36c:   e92d0ff0    push    {r4, r5, r6, r7, r8, r9, sl, fp}
 370:   e24dd010    sub sp, sp, #16   ; <-- Decrement of SP
 374:   e58d0004    str r0, [sp, #4]
 378:   e58d300c    str r3, [sp, #12]
 37c:   e1d330f0    ldrsh   r3, [r3]
 380:   e59d000c    ldr r0, [sp, #12]
 384:   e5d0c002    ldrb    ip, [r0, #2]
 388:   e59f0118    ldr r0, [pc, #280]  ; 4a8 <adpcm_coder+0x13c>
 38c:   e790010c    ldr r0, [r0, ip, lsl #2]
 390:   e3520000    cmp r2, #0
 394:   da00003d    ble 490 <adpcm_coder+0x124>
 398:   e58d1000    str r1, [sp]

GDB的一些输出,可能会有所帮助。

$ arm-none-eabi-gdb my_ctop_IR.elf

(gdb) target sim
Connected to the simulator.

(gdb) load
Loading section .text, size 0x898 vma 0x0
Loading section .rodata, size 0x200 vma 0x898
Loading section .data, size 0x14e768 vma 0xa98
Start address 0x40
Transfer rate: 10981376 bits in <1 sec.

(gdb) b adpcm_coder
Breakpoint 1 at 0x37c: file adpcm_IR.c, line 106.

(gdb) run
Starting program: /home/gaurav/eclipse-workspace/hostCompiledSimulation/instrument/examples/adpcm/my_ctop_IR.elf 

Breakpoint 1, adpcm_coder (indata=0x14f208, outdata=0x154208 "", len=10240, state=0x14f204) at adpcm_IR.c:106
106   valpred = state->valprev;

(gdb) info scope adpcm_coder
Scope for adpcm_coder:
Symbol indata is a variable with multiple locations, length 4.
Symbol outdata is a variable with multiple locations, length 4.
Symbol len is a variable with multiple locations, length 4.
Symbol state is a variable with multiple locations, length 4.
Symbol valpred_41 is optimized out.
Symbol index_40 is a variable with multiple locations, length 4.
Symbol index_38 is optimized out.
Symbol delta_37 is a variable with multiple locations, length 4.
Symbol step_36 is a variable with multiple locations, length 4.
Symbol step_35 is a variable with multiple locations, length 4.
Symbol valpred_34 is a variable with multiple locations, length 4.
Symbol ivtmp_28 is a variable in register r8, length 4.
Symbol bufferstep is a variable in register r6, length 4.
Symbol outputbuffer is a variable with complex or multiple locations (DWARF2), length 4.
Symbol index is a variable with multiple locations, length 4.
Symbol vpdiff is a variable with multiple locations, length 4.
Symbol valpred is a variable with multiple locations, length 4.
Symbol step is a variable with multiple locations, length 4.
Symbol diff is a variable with multiple locations, length 4.
Symbol delta is a variable with multiple locations, length 4.
Symbol sign is a variable in register r7, length 4.
Symbol outp is a variable with complex or multiple locations (DWARF2), length 4.

我还必须指出函数的源代码实际上有更多的局部变量,但这些似乎已经被编译器优化了。当我尝试打印gdb命令 info scope 输出中列出的变量的地址时,我只看到2个带有堆栈地址的变量。这就是我得出的结论,该函数只有2个局部变量。

此致 拉夫

2 个答案:

答案 0 :(得分:3)

除了你的两个变量之外,函数(如果它们不是叶子函数)也需要在某处保存返回地址,这样它们就可以返回。此外,正常的ARM ABI要求堆栈始终为8字节对齐。因此,您需要将总共12个字节存储在堆栈中,这将被四舍五入为8的倍数以进行对齐。

Leaf函数不需要任何堆栈空间,因为它们不需要保存返回地址,并且可以将本地变量保存在暂存寄存器中(如果有4个或更少的本地变量)。

答案 1 :(得分:0)

实际上,你的2个整数可能不是堆栈中使用的16个字节的一部分。 ARM是RISC处理器,一种加载/存储架构。这意味着它永远不会直接在内存中工作。相反,它使用内部寄存器,在内部寄存器中从内存加载值,计算thoses值,然后将其存储在内存中。

如果您的两个整数仅存在于您的函数中,则将其放入内存中是没用的。寄存器将完成工作,您可以避免加载/存储操作。

那么,你的筹码是什么?要知道的唯一方法是看看装配。幸运的是,ARM程序集非常容易阅读。但是让我们猜一下:如果你的函数调用另一个函数,你必须保留你的返回地址(最初在lr寄存器中),你将不得不加载函数地址(它通常不能通过直接寻址调用) ),您必须保存您调用的函数可能修改的寄存器。

很难准确猜测,这实际上取决于你的功能。向我们提供您的功能的反汇编,我们将能够准确地告诉您发生了什么。