Arm assembly add two 64 bit nr

Permalänk
Medlem

Arm assembly add two 64 bit nr

Hej

Jag har ett problem där jag ska implementera en subrutin som addera två 64 bitars tal. Denna ska hetta Add64s. Min fråga är hur jag ska göra för att skapa Add64s. Koden före anropet står här under.

Main
BL Add64s ;CALL Add64
DCD &0420147A, &EB529CB8 ;number1 to add
DCD &3020EB85, &20473118 ;number2 to add
; afterthis call the program should return here
STOP B STOP

* =========================
* Add64 subroutine
* =========================

* Purpose:
* Add two 64 bit values
*
* Initial Condition
* The two parameter values are passed immediately
* following the subroutine call
*
* Final Condition:
* Thesum of the two values is returned in R0 and R1
*
* Registers changed:
* Only R0 and R1
* The flags will respresent the 64-bit addition
*
* Sampel case:
* Initial condition
* param 1 = 0x0420147AEB529CB8
* param 2 = 0x3020EB8520473118
*
* Final condition
* R0 = &34410000
* R1 = &0B99CDD0

kortet heter sam3u-ek

Edit: cpu cortex m3

glömde cpu
Visa signatur

Citera för svar.

Permalänk
Datavetare

Syntax kommer skilja lite beroende på vilken assembler du använder. Den enda jag har koll på för ARM är GNU-assembler där det skulle kunna se ut så här

num1: .word 0x0420147A .word 0xEB529CB8 num2: .word 0x3020EB85 .word 0x20473118 .global add64s @ arguments: r0 points to 'num1', r1 points to 'num2' add64s: push {r2,r3,lr} @ save r2 and r3 + save return address ldr r2, [r1] @ load low part of num2 ldr r3, [r1, #4] @ load high part of num2 ldr r1, [r0, #4] @ load high part of num1 ldr r0, [r0] @ load low part of num1 add r1, r1, r3 @ add low part adc r0, r0, r2 @ add high part with any carry from low part pop {r2,r3,pc} @ restore r2 and r3 + return to caller .global test_add64s test_add64s: adr r0, num1 @ r0 points to first word in num1 adr r1, num2 @ r1 points to first word in num2 b add64s @ branch without setting the link register, add64s will return to the caller of test_add64s

Lade till en liten testfunktion som kan anropas från C t.ex. så här

#include <stdio.h> #include <stdint.h> extern uint64_t test_add64s(void); int main() { uint64_t x = test_add64s(); uint32_t *p = (uint32_t*)&x; printf("%x %x\n", p[0], p[1])); }

Detta kommer skriva ut

34410000 b99cdd0

då ARM ABI på Linux ska returnera 64-bitars tal i register r0 och r1, vilket är precis vad add64s gör.

En snabb sökning med Google pekar på att din uppgift är specificerad för ARMs egen assembler, det blir då en uppgift för dig att översätta till deras syntax

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Syntax kommer skilja lite beroende på vilken assembler du använder. Den enda jag har koll på för ARM är GNU-assembler där det skulle kunna se ut så här

num1: .word 0x0420147A .word 0xEB529CB8 num2: .word 0x3020EB85 .word 0x20473118 .global add64s @ arguments: r0 points to 'num1', r1 points to 'num2' add64s: push {r2,r3,lr} @ save r2 and r3 + save return address ldr r2, [r1] @ load low part of num2 ldr r3, [r1, #4] @ load high part of num2 ldr r1, [r0, #4] @ load high part of num1 ldr r0, [r0] @ load low part of num1 add r1, r1, r3 @ add low part adc r0, r0, r2 @ add high part with any carry from low part pop {r2,r3,pc} @ restore r2 and r3 + return to caller .global test_add64s test_add64s: adr r0, num1 @ r0 points to first word in num1 adr r1, num2 @ r1 points to first word in num2 b add64s @ branch without setting the link register, add64s will return to the caller of test_add64s

Lade till en liten testfunktion som kan anropas från C t.ex. så här

#include <stdio.h> #include <stdint.h> extern uint64_t test_add64s(void); int main() { uint64_t x = test_add64s(); uint32_t *p = (uint32_t*)&x; printf("%x %x\n", p[0], p[1])); }

Detta kommer skriva ut

34410000 b99cdd0

då ARM ABI på Linux ska returnera 64-bitars tal i register r0 och r1, vilket är precis vad add64s gör.

En snabb sökning med Google pekar på att din uppgift är specificerad för ARMs egen assembler, det blir då en uppgift för dig att översätta till deras syntax

Tack för hjälpen

jag har en annan uppgift där jag ska ta och tillverka en subrutin som heter CLZ "count leading zeros"(den ska göra samma som en instruktion med samma namn).

"The CLZ Rd, Rm instruction counts the number of leading zeroes in the value in Rm and returns the result in Rd. The result value is 32 if no bits are set in the source register, and zero if bit 31 is set"

jag har kommit fram till det här under men är inte säker på om det är helt rätt:

NAME main
PUBLIC main

SECTION .text : CODE (2)
THUMB
main

BL CLZ1

B main

CLZ1
MOV R0, #32; r0=32
CMP R1, #0; if r1=0
IT EQ
BXEQ LR; go back

PUSH{R2, R3, LR}
MOV R0, #0;r0=0

LDR R3, =0XFFFF0000

AND R2, R1, R3; SKA VAR 0XFFFF0000
CMP R2, #0;IF R2=0
ADD R0, R0, #16;R0+=16

AND R2, R1, #0XFF000000;BITMASKA FRAM
CMP R2, #0;IF R2=0
ADD R0, R0, #8;R0+=8

AND R2, R1, #0XF0000000;BITMASKA FRAM
CMP R2, #0;IF R2=0
ADD R0, R0, #4;R0+=4

AND R2, R1, #0XC0000000;BITMASKA FRAM
CMP R2, #0;IF R2=0
ADD R0, R0, #2;R0+=2

AND R2, R1, #0X80000000;BITMASKA FRAM
CMP R2, #0;IF R2=0
ADD R0, R0, #1;R0+=1

POP{R2, R3, PC}

BX LR

END

Visa signatur

Citera för svar.

Permalänk
Datavetare

I detta fall använder du Thumb2 och jag har själv aldrig jobbat med detta så ta allt jag skriver med en stor nypa salt. Har läst om Thumb2 så kan se lite saker som du har missat.

Du försöker implmentera denna algoritm (min är i Python här)

def clz (x): if x == 0: return 32 n = 0 if (x & 0xFFFF0000) == 0: n += 16 x <<= 16 if (x & 0xFF000000) == 0: n += 8 x <<= 8 if (x & 0xF0000000) == 0: n += 4 x <<=4 if (x & 0xC0000000) == 0: n += 2 x <<= 2 if (x & 0x80000000) == 0: n += 1 return n

Du har därför systematiskt gjort två fel i varje sådan här block

AND R2, R1, R3; SKA VAR 0XFFFF0000 CMP R2, #0;IF R2=0 ADD R0, R0, #16;R0+=16

Dels saknas skiftning av R1 (som motsvarar x i Python-koden), dels ska den sista additionen bara göras om jämförelsen ovan sätter zero-flaggan.

Vet att Thumb/Thumb2 inte stödjer villkorad körning av instruktioner som 32-bitars läget gör, med Thumb2 har "ITxyz" som gör upp till de 3 nästföljade instruktionerna villkorade på det vilkor som följer efter ITxyz uttrycket. Så det borde se ut något åt det här hållet

AND R2, R1, R3; SKA VAR 0XFFFF0000 CMP R2, #0;IF R2=0 ITT EQ ADDEQ R0, R0, #16;R0+=16 LSLEQ R1, R1, #16 ;R1<<=16

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

I detta fall använder du Thumb2 och jag har själv aldrig jobbat med detta så ta allt jag skriver med en stor nypa salt. Har läst om Thumb2 så kan se lite saker som du har missat.

Du försöker implmentera denna algoritm (min är i Python här)

def clz (x): if x == 0: return 32 n = 0 if (x & 0xFFFF0000) == 0: n += 16 x <<= 16 if (x & 0xFF000000) == 0: n += 8 x <<= 8 if (x & 0xF0000000) == 0: n += 4 x <<=4 if (x & 0xC0000000) == 0: n += 2 x <<= 2 if (x & 0x80000000) == 0: n += 1 return n

Du har därför systematiskt gjort två fel i varje sådan här block

AND R2, R1, R3; SKA VAR 0XFFFF0000 CMP R2, #0;IF R2=0 ADD R0, R0, #16;R0+=16

Dels saknas skiftning av R1 (som motsvarar x i Python-koden), dels ska den sista additionen bara göras om jämförelsen ovan sätter zero-flaggan.

Vet att Thumb/Thumb2 inte stödjer villkorad körning av instruktioner som 32-bitars läget gör, med Thumb2 har "ITxyz" som gör upp till de 3 nästföljade instruktionerna villkorade på det vilkor som följer efter ITxyz uttrycket. Så det borde se ut något åt det här hållet

AND R2, R1, R3; SKA VAR 0XFFFF0000 CMP R2, #0;IF R2=0 ITT EQ ADDEQ R0, R0, #16;R0+=16 LSLEQ R1, R1, #16 ;R1<<=16

Tack för hjälpen.

Visa signatur

Citera för svar.