Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ARMv7 Assembly Language : How to add two uint32_t and return a uint64_t result

Tags:

I am a beginner tinkering with ARM7 Assembly Language programming and have been stuck on this one issue.

I am trying to implement a function in C that takes two unsigned 32 bit vars (uint32_t A and uint32_t B), adds them together and then returns a uint64_t value where the sum contains the carry.

I have included both my C code and ARM7 Assembly Language code below. However, my code doesn't output the correct value; which is probably due to my ASM instructions. Also, I am running Linux with a 32 bit machine.

addVal.s (code below)

.global addVal 

.text

addVal:
    ADD R0, R0, R1
    ADC R0, R1 
    BX LR

addVal.c (code below)

#include <stdio.h>
#include <stdint.h>

extern uint64_t addVal(uint32_t x, uint32_t y);

int main()
{
  uint32_t a, b;
  uint64_t c;
  a = 4000000000;
  b = 1000000000;
  c = addVal(a,b);
  printf("a = %u\r\n", a);
  printf("b = %u\r\n", b);
  printf("c = a + b = %llu\r\n", c);
  return 0;

}

compiled on command line using

as -o addVal addVal.o addVal.s
gcc -o addVal addVal_s.o addVal.c
./addVal
like image 422
Sam T Avatar asked Mar 01 '19 04:03

Sam T


1 Answers

ADC R0, R1 is wrong.

As uint64_t exceeds the size of a single register, it's spread into a subsequent range of registers. The low word resides in R0, high word in R1. So the target register for ADC needs to be R1.

Second problem is that you don't want to add the original low word of R1 into the result high word, but only the carry bit. So you can just clear R1 first.

.text
.arm
.global addVal 
.func addVal
addVal:
    ADDS R0, R0, R1
    MOV R1, #0
    ADC R1, R1, #0
    BX LR
like image 168
Ext3h Avatar answered Nov 23 '22 05:11

Ext3h