告诉编译器以不同的方式翻译某条指令?

Tell the compiler to translate a certain instruction differently?

我正在使用 armccarm-gcc 为 ARM968 处理器编译我的项目。
函数调用返回时,返回指令如下:

Pop {ri-rj, pc}

所有压入的寄存器都在同一条指令中弹出。我想把上面的指令改成这样:

Pop {ri-rj}
Pop {pc}

我可以在使用 Pop 时指示汇编器或编译器在任何 ARM 工具链中遵守上述规则吗?

您可以告诉 gcc 在生成 assembler 后停止处理。您可以手动或使用 sed 编辑 assembler 文件。然后你将 assembler 文件从 binutils 传递到 as 到 assemble 到目标文件。

$ cat test.c
#include <stdio.h>

int main(int argc, char *argv[])
{
        printf ("hello world\n");

        return 0;
}
$ gcc test.c -o test.s -S
cat test.s
        .file   "test.c"
        .section        .rodata
.LC0:
        .string "hello world"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    , %rsp
        movl    %edi, -4(%rbp)
        movq    %rsi, -16(%rbp)
        movl    $.LC0, %edi
        call    puts
        movl    [=10=], %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
        .section        .note.GNU-stack,"",@progbits
$ as test.s -o test.o

根据问题的确切性质,以及您是否严重依赖一些较新的指令,另一种可能性可能是针对 ARMv4T 进行编译。在 ARMv5T 之前,进入 PC 的 ldm 无法互通,因此编译器不会为 v4T 目标发出那种形式的 return 指令。对于一些简单的测试代码,使用 -march=armv5t 编译会生成一个堆栈帧:

   8:   e92d4070        push    {r4, r5, r6, lr}
...
  4c:   d8bd8070        pople   {r4, r5, r6, pc}

而使用 -march=armv4t 编译相同的东西使用相同的序言但使用间接 return 序列(上面是循环内的条件 return,现在它也被移动到函数末尾):

  48:   da000006        ble     68 <func+0x68>
...
  68:   e8bd4070        pop     {r4, r5, r6, lr}
  6c:   e12fff1e        bx      lr

当然,这是否与两个单独的 pop 具有相同的效果取决于系统中的潜在错误是什么 - 如果它类似于 ldm 和指令的数据获取之间的时间获取跳跃本身,那么这可能是足够等价的;可以想象它可能是完全不同的东西,比如一个损坏的内存系统截断了超过一定大小的 AHB 突发,所以它是在单个 ldm 中传输的寄存器数量这就是问题所在,但在那种情况下我也希望查看 memcpy 之类的问题,这些问题不太容易解决。