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

查看:20
本文介绍了理解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 ?

感谢您的帮助,

问候,

罗布.

推荐答案

这在某种程度上取决于代码没有(完全)优化,使其看起来相当混乱.

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天全站免登陆