【问题标题】:Function call with more than 4 registers ARM assembly具有超过 4 个寄存器的函数调用 ARM 程序集
【发布时间】:2015-11-06 03:56:02
【问题描述】:

我正在尝试将 r0-r5 传递给函数 check。然而,只有寄存器 r0-r3 是通过引用复制的。在我的主要功能中,我有这个代码。

    push {lr}
    mov r0, #1
    mov r1, #2
    mov r2, #3
    mov r3, #4
    mov r4, #5
    mov r5, #6
    bl check
    pop {lr}
    bx lr

在我的check 函数中,我有这个代码。这是在一个单独的文件中,也不确定这是否重要

    m: .asciz "%d, %d ~ (%d, %d, %d)
    ...
    push {lr}
    ldr r0, =m
    bl printf
    pop {lr}
    bx lr

这个的输出是2, 3 ~ (4, 33772, 1994545180)。我正在尝试学习组装,所以你能用谷歌搜索解释一下我知道我需要使用堆栈但是,我不知道如何使用它并想学习如何使用它。提前致谢。

【问题讨论】:

  • 如果您对所涉及的所有内容都不太熟悉,这可能有点难读,但作为参考,您可以找到 EABI 调用约定的官方定义here

标签: function assembly stack arm gnu


【解决方案1】:

你可以试试看

void check ( unsigned int, unsigned int, unsigned int, unsigned int, unsigned int );

void call_check ( void )
{
    check(1,2,3,4,5);
}

arm-linux-gnueabi-gcc -c -O2 check.c -o check.o arm-linux-gnueabi-objdump -D check.o

00000000 <call_check>:
   0:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
   4:   e3a03005    mov r3, #5
   8:   e24dd00c    sub sp, sp, #12
   c:   e58d3000    str r3, [sp]
  10:   e3a00001    mov r0, #1
  14:   e3a01002    mov r1, #2
  18:   e3a02003    mov r2, #3
  1c:   e3a03004    mov r3, #4
  20:   ebfffffe    bl  0 <check>
  24:   e28dd00c    add sp, sp, #12
  28:   e8bd8000    ldmfd   sp!, {pc}

当然,这可以手动优化并且仍然可以正常工作。也许他们将堆栈保持在 16 字节/4 字/64 位边界上是对堆栈指针进行额外 12 字节修改的原因吗?不知道。但除此之外,您可以看到您自然需要保存链接寄存器,因为您正在调用另一个函数。 r0 - r3 是显而易见的,然后根据 eabi,堆栈中的第一件事是参数的第 5 个字。

同样,对于您的检查功能,您可以简单地让编译器帮助您开始。如果您查看您的代码,r0 作为您的第一个参数进入,然后您通过将其更改为 printf 的第一个参数来丢弃它。您需要 6 个参数才能传递 printf。您需要将它们移到一个上。要检查的第一个参数是 printf 的第二个参数,要检查的第二个参数是 printf 的第三个参数,依此类推。所以代码必须做这个转变(其中两个现在在堆栈上)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 2017-12-07
    • 2012-02-24
    • 1970-01-01
    相关资源
    最近更新 更多