abstract42
abstract42

Reputation: 33

In arm assembly, how can I create an array then increment each element by 10, for example?

I would like to modify and complete an example found in my textbook (Harris-Harris). How can I make a program that declares an array of 5 elements for example and then increments each element by 10? This program must also print the elements of the array.

enter image description here

I've searched some resources and figured out that there are various ways to create an array in Assembly ARM. In these examples that I found, however, there are directives that I don't understand (for example .word or .skip) that are not explained in my textbook.

Upvotes: 0

Views: 730

Answers (1)

atl
atl

Reputation: 773

Hope this helps. This example uses the stack to allocate the array.

See assembly memory allocation directives for more help on allocating global variables. Moving the variable scores into global scope of the file test.c below can reveal the assembly code for that sort of solution.

What is below comes from a quick walk thru of Hello world for bare metal ARM using QEMU

Output of these steps will add 10 to 5 array integers and print their values. The code is in c but instructions are provided on how to display the code as assembly so you can study the array allocation and utilization.

Here is the expected output:

SCORE  10
SCORE  10
SCORE  10
SCORE  10
SCORE  10
ctrl-a x
QEMU: Terminated

These are the commands, notice startup.s is assembly code, test.c is c code like left side of your post, and test.ld is a linker script file to create the image QEMU needs test.bin to execute. Also, notice test.elf is available with debug symbols for use in gdb.

arm-none-eabi-as -mcpu=arm926ej-s -g startup.s -o startup.o
arm-none-eabi-gcc -c -mcpu=arm926ej-s -g test.c -o test.o
arm-none-eabi-ld -T test.ld test.o startup.o -o test.elf
arm-none-eabi-objcopy -O binary test.elf test.bin

qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin

To examine assembly code in gdb see commands below.

Notice the array scores in this code is on the stack, read about local stack variables for ARM assembly here and examine the assembly instructions below at 0x10888 where sp is incremented by 24 (20 for scores and 4 for i).

qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin -s -S

arm-none-eabi-gdb test.elf -ex "target remote:1234"
(gdb) b c_entry
(gdb) cont
(gdb) x/20i c_entry
   0x10180 <c_entry>:   push    {r11, lr}
   0x10184 <c_entry+4>: add r11, sp, #4
   0x10188 <c_entry+8>: sub sp, sp, #24

I use a macbook and install tools like this, they end up in /usr/local/bin:

brew install --cask gcc-arm-embedded
brew install qemu

The c code used is similar to what you posted and combines the article snip w/ a function to print an integer. References are inline of the code.

// test.c
// https://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/
volatile unsigned int *const UART0DR = (unsigned int *)0x101f1000;

void print_uart0(const char *s) {
  while (*s != '\0') {             /* Loop until end of string */
    *UART0DR = (unsigned int)(*s); /* Transmit char */
    s++;                           /* Next char */
  }
}

// https://www.geeksforgeeks.org/c-program-to-print-all-digits-of-a-given-number/
void print_int(int N) {
  #define MAX 10
  char arr[MAX]; // To store the digit of the number N
  int i = MAX - 1;
  int minus = ( N < 0 );
  int r;

  arr[i--] = 0;
  while (N != 0) { // Till N becomes 0
    r = N % 10;    // Extract the last digit of N
    arr[i--] = r + '0';  // Put the digit in arr[]
    N = N / 10;    // Update N to N/10 to extract next last digit
  }
  arr[i] = ( minus ) ? '-' : ' ';
  print_uart0(arr + i );
}

void c_entry() {
  int i;
  int scores[5] = {0, 0, 0, 0, 0};
  for (i = 0; i < 5; i++) {
    scores[i] += 10;
    print_uart0("SCORE ");
    print_int( scores[i] );
    print_uart0("\n");
  }
}

Using the same startup.s assembly from article:

.global _Reset
_Reset:
 LDR sp, =stack_top
 BL c_entry
 B .

Using the same linker script from article:

ENTRY(_Reset)
SECTIONS
{
 . = 0x10000;
 .startup . : { startup.o(.text) }
 .text : { *(.text) }
 .data : { *(.data) }
 .bss : { *(.bss COMMON) }
 . = ALIGN(8);
 . = . + 0x1000; /* 4kB of stack memory */
 stack_top = .;
}

Upvotes: 1

Related Questions