【问题标题】:Branching in Arm Assembly手臂装配中的分支
【发布时间】:2012-06-07 13:27:57
【问题描述】:

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

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

ma​​thLib.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)

program.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;
}

编辑

这是我最后想到的

@ 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_mod             @ This makes it a real symbol


@ ABS Func. Compiler just does "rsblt   r0, r0, #0" but this is more fun.
@int asm_abs(int a)

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 a (r0) to set ensure negative
    cmp     r2, r0              @ compare a for-sure neg input with input a
    bne     asm_abs_ret         @ if not equal, input was pos, so return
    sub     r0, r0, r0, lsl#1   @ else set a = a - (2*a)
asm_abs_ret:
    mov     pc, lr              @ set program counter to lr (was set by caller)

@ Take two numbers, and return abs(a) + abs(b)
@ int asm_two_abs(int a, int b)

asm_two_abs:                        @ start of function definition
    stmfd   sp!, {r4-r6}        @ push the non-scratch registers we'll use on the stack
    mov     r4, lr              @ store link register in r4
    mov     r6, r1              @ store second argument b in r6
    bl      asm_abs             @ set a (r0) = abs(a)
    mov     r5, r0              @ store abs(a) in r5
    mov     r0, r6              @ set r0 = b
    bl      asm_abs             @ should set b = abs(b)
    add     r0, r0, r5          @ set r0 = abs(b) + abs(a)  
    mov     lr, r4              @ restore link register
    ldmfd   sp!, {r4-r6}        @ restore non-scratch registers we used
    mov     pc, lr              @ set program counter to lr (was set by caller)

【问题讨论】:

    标签: assembly arm


    【解决方案1】:

    你没有保留你的链接寄存器。

    bl 跳转到一个地址并将链接寄存器 r14 设置为返回地址

    bl hello
    asdf <- lr points here
    
    
    hello:
      push {lr}
      bl there
      pop {lr}
      bx lr
    
    
    there:
      stuff
      bx lr
    

    由于 hello 调用了另一个函数,它需要保存链接寄存器以知道如何返回给调用它的人。没有,因为它不会对其他任何人 bl(不修改 lr)。

    【讨论】:

    • 简答:bl指令修改lr(r14),asm_two_abs做的第一件事就是修改r14,你需要保留r14以便最后使用(mov pc,lr)跨度>
    • 我会养成使用 bx lr 而不是 mov pc,lr 的习惯,除非你使用的是比 ARM7TDMI 更老的东西。
    • push {r4, r5, lr} 和后来的pop {r4, r5, pc} 也很常见。
    • 是的,我讨厌 pop{...pc} 会根据体系结构做两种不同的事情...而且 ARM 已经开始鼓励或强制使用 64 位的倍数,而不是推动三个 push{r4 ,r5,lr} 他们想要一些虚拟寄存器来保持堆栈对齐 push {r4,r5,r6,pc}。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多