viral trata que moto hoy assembly arm

assembly - trata - video viral de la moto



Ramificación en el ensamblaje del brazo (1)

No está preservando su registro de enlace.

bl se ramifica a una dirección y establece el registro de enlace r14 a la dirección de retorno

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

Como hola llama a otra función, necesita guardar el registro de enlace para saber cómo regresar a quien lo haya llamado. no lo hace, no lo hace a nadie más (no modifica lr).

Estoy usando la cadena de herramientas GNU ARM (arm-elf-gcc). Tengo un archivo de ensamblaje y un archivo c que llama a los métodos globales definidos en el archivo de ensamblaje. Puedo invocar con éxito un método de ensamblaje único desde c, pero no puedo encontrar la forma de llamar a un método de ensamblaje que a su vez llame a otro método de ensamblaje. Me gustaría que ambos métodos de ensamblado se puedan llamar desde c y estén en el mismo archivo.

Aquí están los dos archivos. Cuando ejecuto el programa, nunca vuelve, así que sé que hay un problema en la bifurcación.

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)

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

EDITAR

Esto es lo que se me ocurrió al final

@ 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)