Assembly 臂组件中的分支

Assembly 臂组件中的分支,assembly,arm,Assembly,Arm,我正在使用GNU ARM工具链(ARM elf gcc)。我有一个程序集文件和一个调用程序集文件中定义的全局方法的c文件。我可以成功地从c中调用单个汇编方法,但我不知道如何调用本身调用另一个汇编方法的汇编方法。我希望这两个程序集方法都可以从c调用,并且在同一个文件中 这是两个文件。当我运行程序时,它永远不会返回,所以我知道分支中存在问题 mathLib.s @ ARM Assembler Library for absolute value .align 2

我正在使用GNU ARM工具链(ARM elf gcc)。我有一个程序集文件和一个调用程序集文件中定义的全局方法的c文件。我可以成功地从c中调用单个汇编方法,但我不知道如何调用本身调用另一个汇编方法的汇编方法。我希望这两个程序集方法都可以从c调用,并且在同一个文件中

这是两个文件。当我运行程序时,它永远不会返回,所以我知道分支中存在问题

mathLib.s

@ ARM Assembler Library for absolute value

    .align 2                    @ Align to word boundary
    .arm                        @ This is ARM code
    .global asm_abs             @ This makes it a real symbol
    .global asm_two_abs         @ This makes it a real symbol

@ ABS Func. Compiler just does "rsblt   r0, r0, #0" but this is more fun.
    asm_abs:                        @ Start of function definition
        mov     r2, #1              @ Set the least bit high in r2
        mov     r2, r2, lsl#31      @ Shift that bit all the way to the sign slot
        orr     r2, r2, r0          @ XOR with input (r0) to set ensure negative
        cmp     r2, r0              @ compare a for-sure neg input with input
        bne     asm_abs_ret         @ if not equal, input was pos, so return
        sub     r0, r0, r0, lsl#1   @ else set input = input - (2*input)
    asm_abs_ret:
        mov     pc, lr              @ Set program counter to lr (was set by caller)

    asm_two_abs:                        @ Start of function definition
        bl      asm_abs                 @ Should set r0 = abs(r0)
        mov     r2, r0                  @ set r2 = r0
        mov     r0, r1                  @ set r0 = r1
        bl      asm_abs                 @ Should set r0 = abs(r0)
        add     r0, r0, r2              @ set r0 = r0 + r2  
        mov     pc, lr                  @ Set program counter to lr (was set by caller)
程序.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    extern int asm_abs(int a);
    extern int asm_two_abs(int a, int b);

    int m = atoi(argv[1]);
    int n = atoi(argv[2]);
    int r = asm_two_abs(m, n); 

    printf("%d\n", r);

    return 0;
}

您没有保存链接寄存器

bl分支到一个地址,并将链接寄存器r14设置为返回地址

bl hello
asdf <- lr points here


hello:
  push {lr}
  bl there
  pop {lr}
  bx lr


there:
  stuff
  bx lr
你好
asdf简短的回答:指令bl修改lr(r14),asm_two_abs做的第一件事就是修改r14,你需要保留r14,这样你可以在最后使用它(mov pc,lr)。我会习惯使用bx lr,而不是mov pc,lr,除非你使用的是比ARM7TDMI旧的东西。推送{r4,r5,lr}也很常见和后来的
pop{r4,r5,pc}
是的,我讨厌pop{…pc}根据体系结构做两件不同的事情…而且ARM已经开始鼓励或强制使用64位的倍数,所以他们不需要推三个push{r4,r5,lr},而是需要一些虚拟寄存器来保持堆栈对齐push{r4,r5,r6,pc}。
bl hello
asdf <- lr points here


hello:
  push {lr}
  bl there
  pop {lr}
  bx lr


there:
  stuff
  bx lr