2012-06-07 22 views
3

我正在使用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) 

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) 

回答

14

您不保留鏈接寄存器。

BL分支到一個地址,並設置鏈接寄存器R14的返回地址

bl hello 
asdf <- lr points here 


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


there: 
    stuff 
    bx lr 

由於你好調用它需要保存鏈接寄存器知道如何回去給誰就給誰把它稱爲另一種功能。有沒有像其他人不會bl(不修改lr)。

+1

更短的回答:指令bl修改lr(r14),asm_two_abs所做的第一件事是修改r14,您需要保留r14,以便您可以在末尾使用它(mov pc,lr) –

+4

我會陷入習慣使用bx lr,而不是mov pc,lr,除非你使用的是比ARM7TDMI更早的東西。 –

+0

'push {r4,r5,lr}'和後來的'pop {r4,r5,pc}'也很常見。 – Renate