MSP430程序集堆栈指针行为 [英] MSP430 Assembly Stack Pointer Behavior

查看:320
本文介绍了MSP430程序集堆栈指针行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试分析通过msp430-gcc生成的简单Assembly文件时,我偶然发现了一组我不理解的有关处理帧指针和MSP430的堆栈指针的指令.

While trying to analyze a simple Assembly file generated through the msp430-gcc, I stumbled upon a set of instructions that I don't understand dealing with the frame pointer and the MSP430's stack pointer.

C程序:

#include "msp430g2553.h"

int main()
{
  int i;

  for(i = 0; i < 3; i++);

}

汇编减指令:

main:
        mov     r1, r4 ;Stores address of stack pointer in r4(frame pointer)
        add     #2, r4 ; ?
        sub     #2, r1 ; subtract 2 to allocate int i
        mov     #0, -4(r4) ; assign 0 to i
        jmp     .L2 ; start loop
.L3:
        add     #1, -4(r4) ; Adds one to int i
.L2:
        cmp     #3, -4(r4) ; Compare to #3
        jl      .L3 ; jump to .L3 if true
        add     #2, r1 ; deallocate int i
.Lfe1:
        .size   main,.Lfe1-main

我尝试注释代码以跟踪程序的执行,但是我不理解行add #2, r4.究竟发生了什么?为什么在-4(r4)处引用int i?

I tried commenting the code to trace the program's execution, but I don't understand the line add #2, r4. What exactly is happening here, and why is int i being referenced at -4(r4)?

推荐答案

通常,您在函数中要做的第一件事是:

Normally the first thing you'll do in a function is:

push r4

将当前框架指针保存在堆栈上,因此您可以为要调用的函数设置新的框架指针,然后再恢复旧的框架指针. push会自动将堆栈指针减2,因此当您这样做时:

to save the current frame pointer on the stack, so you can set a new frame pointer for the function you're about to call, and then restore the old one afterwards. push will automatically decrement the stack pointer by 2, so when you then do:

mov r1, r4

推送到r4的地址将高于您刚刚推送到堆栈上的值(此处高于"是指堆栈向下增长-实际上在数字上低于该值)内存地址).您将希望帧指针实际上指向您刚压入堆栈的值之下,因此您可以将其递增2以实现以下目的:

the address pushed on to r4 will be above the value you just pushed on the stack ("above" here in the sense that the stack grows downwards - it's actually below in terms of numeric memory addresses). You'll want the frame pointer to actually point below the value you just pushed onto the stack, so you increment it by two to achieve this with:

add #2, r4

因为main()是第一个执行的函数,所以您没有要保存的现有帧指针,因此在这里看到的是movadd,而没有push

Because main() is the first function executed, you don't have an existing frame pointer to save, so what you're seeing here is the mov and the add in the absence of the push.

当您进行实际的函数调用时,它将更有意义,并且您将看到整个过程:

It'll make more sense when you make an actual function call, and you'll see the whole thing:

push r4
mov  r1, r4
add  #2, r4

完成此操作后,-2(r4)将引用您刚刚压入堆栈的帧指针的前一个值,并且由于您没有将两个指针加到堆栈指针的值上,因此-2(r4)也会相等.

After you've done this, -2(r4) will refer to the previous value of the frame pointer that you just pushed onto the stack, and since you haven't added two to the value of the stack pointer, -2(r4) will equal that, too.

现在为局部变量i分配16位时,必须从堆栈指针中减去2为其腾出空间,因此i的地址将为-4(r4).

When you now allocate 16 bits for your local variable i, you'll have to subtract 2 from the stack pointer to make room for it, and the address of i will therefore be -4(r4).

作为一个示例,假设堆栈指针包含0x200,而帧指针包含0x202,然后您要调用一个函数.您从这样的堆栈开始:

As an example, suppose the stack pointer contains 0x200 and the frame pointer contains 0x202, and you then want to call a function. You start off with a stack like this:

      r4 --> 0x202    ---------------------
                             <empty>
      r1 --> 0x200    ---------------------

从函数返回后,您将要恢复帧指针的当前值,因此要做的第一件事是将其压入堆栈以保存它.在push r4之后,值0x202因此被压入内存位置0x200(即r1所指向的堆栈的顶部),并且堆栈指针减小了2为其留出空间,所以你得到:

After you return from your function, you're going to want to restore the current value of the frame pointer, so the first thing you do is push it onto the stack to save it. After push r4, the value 0x202 therefore gets pushed onto memory location 0x200 (i.e. the top of the stack pointed to by r1), and the stack pointer gets decremented by 2 to make room for it, so you get:

      r4 --> 0x202    ---------------------
                             <empty>
             0x200    ---------------------
                              0x202
      r1 --> 0x1FE    ---------------------

已经将帧指针的前一个值压入堆栈,现在您要将帧指针的当前值设置为当前堆栈帧的基数,因此可以通过将新的堆栈指​​针移到r4,您会得到:

Having pushed the previous value of the frame pointer onto the stack, you now want to set the current value of the frame pointer to the base of your current stack frame, so you start this off by moving the new stack pointer into r4, and you get:

             0x202    ---------------------
                             <empty>
             0x200    ---------------------
                              0x202
r1 == r4 --> 0x1FE    ---------------------

框架指针的旧值是当前堆栈框架中的第一件事,因此您希望r4指向之前的指针,而不是之后的指针.为此,您将2添加到r4,您将得到:

The old value of the frame pointer is the first thing in your current stack frame, so you want r4 to point before that, not after it. To do this you add 2 to r4, and you get:

             0x202    ---------------------
                              <empty>
      r4 --> 0x200    ---------------------
                               0x202
      r1 --> 0x1FE    ---------------------

您现在所处的位置是r4指向堆栈框架的底部,而r1指向堆栈框架的顶部(您想要的位置).此时,当前堆栈帧中唯一实际的事情是在函数开始时将其推入帧指针的先前值.

The position you're in now is that r4 points to the bottom of your stack frame, and r1 points to the top of it, which is where you want to be. The only thing actually in your current stack frame at this point is the previous value of the frame pointer that you pushed onto it at the start of the function.

然后,将堆栈指针递减2以便为新的局部变量腾出空间,最后得到:

Then you decrement the stack pointer by 2 to make room for your new local variable, and you end up with:

             0x202    ---------------------
                             <empty>
      r4 --> 0x200    ---------------------
                              0x202
             0x1FE    ---------------------
                        <uninitialized i>
      r1 --> 0x1FC    ---------------------

,您会看到i存储在0x1FC,即-4(r4).再次位于r4指向堆栈框架底部,而r1指向堆栈框架顶部的位置,但是现在您在当前堆栈框架中有两个16位值,因此这两个指针相隔4个字节.

and you can see that i is stored at 0x1FC, which is -4(r4). Once again you're in the position where r4 points to the bottom of your stack frame, and r1 points to the top of it, but now you have two 16 bit values in your current stack frame, so the two pointers are 4 bytes apart.

当您准备在函数末尾返回时,您将add #2, r1为本地变量i重新分配"内存.这将为您提供:

When you're ready to return at the end of your function, you'll add #2, r1 to "deallocate" the memory for your local variable i. This will give you:

             0x202    ---------------------
                              <empty>
      r4 --> 0x200    ---------------------
                               0x202
      r1 --> 0x1FE    ---------------------

然后您将单击pop r4,它将最后一个值从堆栈中弹出(现在为0x202,即帧指针的原始值),将其放入r4,然后将堆栈指针增加2以反映该值已从堆栈中删除,这将使您处于:

You'll then pop r4, which will pop the last value off the stack (which is now 0x202, the original value of the frame pointer), put it into r4, and increment the stack pointer by 2 to reflect that that value has been removed from the stack, which will leave you at:

      r4 --> 0x202    ---------------------
                             <empty>
      r1 --> 0x200    ---------------------

这是您刚开始的地方,并且在函数调用后已完美清理了堆栈.

which is right where you started, and you've cleaned up the stack perfectly after your function call.

请注意,这略有简化,因为当您进行函数调用时,程序计数器也将被压入堆栈,然后在返回时又弹出并恢复,而上面的示例并未显示这一点,但是那里正发生着同样的事情.

Note this is slightly simplified since when you do make a function call, the program counter is also going to get pushed onto the stack, and then popped and restored again when you return, and the above example doesn't show that, but exactly the same kind of thing is going on there.

这篇关于MSP430程序集堆栈指针行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆