2012-06-07 3 views
3

Я использую toolchain 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; 
} 

EDIT

Вот что я придумал в конце концов

@ 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

Вы не сохраняете свой реестр.

бла ветвь к адресу и устанавливает регистр r14 ссылки на обратный адрес

bl hello 
asdf <- lr points here 


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


there: 
    stuff 
    bx lr 

Поскольку привет вызывает другую функцию, необходимую для сохранения регистра связи, чтобы узнать, как получить обратно, кого называл его. там не так, как это никому не нравится (не меняет 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

Смежные вопросы