0

I wrote some assembly code on Keil where if an element in array is < 5, the program increments that element. Trouble is, the ARM code does not change the values of array1 in memory. What changes do I need to make in order to do so?

    ADR r0, array1      ; loads address of 'a' to r0

    MOV r1, #0          ; r1 = index

L0  CMP r1, #8
    BGE stop
    LDR r2, [r0, r1, LSL#2] ; load content of array1[index] to r2
    CMP r2, #5
    ADDLT   r2, r2, #1      ; array1[index]++
    STRLT   r2, [r0, r1, LSL#2] ; store r2 as content of array1[index]
    ADD r1, r1, #1      ; index++
    B   L0

stop B  stop
array1  DCD 1, 7, 4, 9, 2, 3, 8, 6
    END
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
John Park
  • 335
  • 5
  • 23
  • I guess the `addlt` *does* also update flag register, so the `strlt` is not any more in "less than" state, and is not executed. Can't recall ARM details to be 100% sure, but I think some exceptions about when instruction updates flags were rather in thumb mode? Well, consult your manuals or some simulator/debugger, what your `addlt` does. BTW, having debugger and some simulator/board is essential so you can check yourself, what is the state of CPU ahead of `strlt` and why it is not executed. ... in case it's modified flags, you will have to decide if you want rather branch, or store every val. – Ped7g Mar 23 '19 at 07:22
  • 3
    I can't see why this wouldn't work, so my question is - how do you know it does not work? How to you examine the memory, what tools do you use? – tum_ Mar 23 '19 at 10:07
  • 2
    @Ped7g `addlt` should not set any flags. That would be `addslt` instead. – fuz Mar 23 '19 at 11:47
  • @fuz then I'm wrong and agree with tum... this should work well on first sight, i.e. one should debug it to see what actually happens. – Ped7g Mar 23 '19 at 12:13
  • @Ped7g I now know the reason why. STR seems to work only for values between 0x40000000 and 0x40003FFF. Since array1 is located in address 0x00000010 or 0x0000000A, this address falls outside the boundary of where STR can work. As a follow up, does anyone know why STR is limited to writing values to this restricted range of addresses? – John Park Mar 25 '19 at 01:05
  • @tum_ I'm using keil uVision5 with processor configuration NXP LPC2104 – John Park Mar 25 '19 at 01:08
  • I see. And what is your environment? Does the code run on a real chip or is this a simulation of some sort, is there an OS? How do you get to running the code - is there a linker involved that would generate a .map file for you? I'm not familiar with uVision, always used GNU tools... – tum_ Mar 25 '19 at 06:05
  • @JohnPark well, that's 16kB area... from a quick google of "NXP LPC2104" it seems that may be actually what it is, the 16kB of static RAM. Writing value into address space where no memory chip is mapped is kinda undefined (on some platforms that may wrap around and land into some memory chip mapped officially elsewhere, in your case it seems the value is just lost). Check that "NXP LPC2104" data sheet, how the HW is mapped and which areas of address space are valid. Also check if there are some examples, usually things like 0x40000000 assigned to `.data` is done by linker, to make life easier. – Ped7g Mar 25 '19 at 07:12
  • 1
    If you are new to assembly, try to shift your thinking process a bit more toward actually mapping things physically. The HW is very physical, and while coding in assembly, you have to be often aware of where your code will land, how much of space it occupies, and which resources it does use. Lot of this can be avoided in higher level languages as they hold your hand, and produce sort of "abstract" air around you, while in assembly you work directly with the provided HW, as is. – Ped7g Mar 25 '19 at 07:16
  • @Ped7g He's fired a new Q. on this: https://stackoverflow.com/questions/55330044/why-does-str-only-work-for-addresses-between-0x40000000-and-0x40003fff – tum_ Mar 25 '19 at 10:29

1 Answers1

1

Below is the memory map for Cortex-M3 DesignStart Eval. Granted, this is Cortex-M rather than ATM7TDMI, but it is good as an example.

You can see here, FLASH region, various expansion regions, peripherals and different types of RAM. You can compare this to the memory map of the LPC2140 to check the relevant addresses for your device.

Generally, for program code, FLASH regions are read only (a special control sequence is required to modify FLASH, specific to the actual part). The areas marked as expansion in this diagram have nothing. Accesses to these should fault (from an idealistic point of view), but could also just be ignored. In DesignStart, they are regions for designers to add their own hardware. The only region that your code can reliably use for read/write storage are the RAM regions. ARM-7 does not have the clearly defined memory map of ARMv7-M, but for an LPC2140 device, you can be sure there is RAM between 0x40000000 and 0x40001FFF (as well as FLASH starting from 0x00000000).

The ARM architecture allows you to use a code region as data (so litterals can be embedded in the code, and accessed just like variables). It does not guarantee that the code memory can be modified.

Fig 4-1 from ARM100894_0000_00_en

Fig 4-1 from ARM100894_0000_00_en

Sean Houlihane
  • 1,698
  • 16
  • 22