了解ARM gcc的函数调用编译 [英] Understanding compilation of ARM gcc to function call

查看:107
本文介绍了了解ARM gcc的函数调用编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个C代码:

    void initPIO_Port(AT91S_PIO *port)
    {
        port->PIO_PER=1<<PIN;
        port->PIO_OER=1<<PIN;
    }   // initPIO_Port

    int main(void)
    {         
      initPIO_Port(PORT);

          /* Loop for ever */
          while (1) {
              ...
          };      
   }

通过arm-gcc转换为ARM程序集:

translated to ARM assembly by arm-gcc :

main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
@int main(void)
@{         
@  initPIO_Port(PORT);
@  while (1) {
 ....
@ };      
@}

stmfd   sp!, {fp, lr}

add fp, sp, #4

ldr r0, .L13
bl  initPIO_Port

.L12:    
    ...

b   .L12




initPIO_Port:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.

@ void initPIO_Port(AT91S_PIO *port)

str fp, [sp, #-4]!
add fp, sp, #0

sub sp, sp, #12    @ why subtract 12 - we're not using sp in following code ?
str r0, [fp, #-8]  @ first empty place is at fp-8? fp points to last full location on stack - is this right ?
                   @ why is input parameter in r0 saved on stack and then read in r3 ?

    ldr r3, [fp, #-8]  @     port->PIO_PER=1<<PIN;
    mov r2, #2
    str r2, [r3, #0]

    ldr r3, [fp, #-8]  @     port->PIO_OER=1<<PIN;
    mov r2, #2
    str r2, [r3, #16]

add sp, fp, #0     @ previous value of sp
ldmfd   sp!, {fp}  @ restore fp
bx  lr             @ return

我在理解fp和sp寄存器的行为时遇到问题:

I've problem understanding behaviour of fp and sp register:

  • 为什么我要从sp中减去12,然后再不使用它?为什么是12?

  • Why do I subtract 12 from sp and then don't use it? Why 12 ?

fp寄存器的用途到底是什么?

What exactly is the purpose of fp register ?

为什么将r0写入堆栈并读取到r3?都不都是为了输入参数吗?

Why is r0 written on stack and read to r3 ? Aren't both meant to be for input parameters ?

感谢您的帮助,

致谢

Rob.

推荐答案

在某种程度上,取决于代码是否(未完全)优化(使代码看上去很混乱).

It's somewhat depending on that the code is not (fully) optimized that makes it look rather confusing.

为什么我要从sp中减去12,然后再不使用它?为什么是12?

Why do I subtract 12 from sp and then don't use it? Why 12 ?

这是为堆栈帧分配空间,它认为需要12个字节的原因是它将使用一个字来保存帧指针,使用一个字来存储局部变量 port ,并且一个可能要保存返回地址(应该调用另一个函数).

This is to allocate space for the stack frame, the reason it thinks it needs 12 bytes is that it will use one word to save the frame pointer, one word to store the local variable port and one probably to save the return address (should it call another function).

fp寄存器的目的到底是什么?

What exactly is the purpose of fp register ?

它是框架指针.它使用它来访问局部变量.实际上,它大部分都是多余的,如果启用优化功能,可能会被优化掉.

It's the frame pointer. It uses this to access local variables. It's actually mostly redundant and may be optimized away if you enable optimizations.

帧指针的一种用法是,如您所见,调用帧的帧指针存储在帧指针的偏移量 0 处.这意味着您可以按照堆栈框架进行调试.

One use of the frame pointer is that as you see the frame pointer of the calling frame is stored at offset 0 of the frame pointer. This means that you can follow the stack frames for debugging purposes.

为什么将r0写在堆栈上并读到r3?都不都是为了输入参数吗?

Why is r0 written on stack and read to r3 ? Aren't both meant to be for input parameters ?

缺乏优化. r0 是第一个输入参数,它存储在帧中为 port 变量分配的空间中,当使用该变量时,将从帧中读取它.完成此操作后,重用 r3 没问题,因为编译器会将保存在 r3 中的参数保存到该参数的帧分配空间中.

It's lack of optimization. r0 is the first input parameter, and it's stored in the frame allocated space for the port variable, when the variable is being used it will be read from the frame. It's no problem to reuse r3 after doing this as the compiler would have saved the parameter passed in r3 to the frame allocated space for that parameter.

同样,如果您启用了优化功能,编译器将意识到它不需要将变量 port 存储在堆栈帧中,它将使其驻留在 r0 .

Again if you had turned on optimization the compiler would have realized that it wouldn't need to store the variable port in the stack frame, it would let it live in r0 instead.

这篇关于了解ARM gcc的函数调用编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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