0% found this document useful (0 votes)
9 views

LAB Memory Access

Uploaded by

Animesh Jain
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

LAB Memory Access

Uploaded by

Animesh Jain
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

LABORATORY ON Advanced Embedded Microcontroller -ARM

SUBJECT CODE: EL62204

January – April 2017

EXPERIMENT #2:

MEMORY ACCESS AND MANIPULATION IN

ARM ASSEMBLY LANGUAGE


To learn

(i) To define code, stack and data areas.


(ii) To use registers as pointers and carry out primitive data movement
operations
(iii) Use of sophisticated indexing modes and multi-register transfer
instructions to speed up execution.

Procedure:

Part I: (i) familiarizing with code, data and stack areas in Keil Assembler

1. Create a new folder where you will keep all programs of this lab. One such name is suggested
- “ARM_assembly_code”. You have been given a zip file
“2_Memory_Access_&_Manipulation.zip” containing pre-formed and predefined project,
EIGHT .s files containing several assembly language programs and this document. Unzip this
file into this folder.

2. Start uV5. If any project opens close it. Your uV5 must have software packs installed for
STM32F401RETx microcontroller.

3. Add file “data_movement_1.s” provided to you in this folder.

4. The template used in this program is similar to used in previous experiment.

5. Note the usage of area at the end of the code for storing data under 3 labels Table1, Table2
and Table3. For the sake of simplicity and homogeneity, we are handling only 32-bit words. It
must be kept in mind that this area is READONLY area.

6. Go through the comments of this program. Our code is inserted after “Reset_Handler”. Notice
the END at the physical end of the program, after the data is stored.
7. Rest of the code above it is to tell the assembler about the processor memory area and to set
interrupt vectors and other initialization. Since we are not adding startup file, our code in
assembly must do this housekeeping.

8. This program uses ADR pseudo-instruction which loads a 32-bit address of labels Table1,
Table2 and Table3 into registers R1, R2 and R3 respectively. The condition is that the location
of these labels in memory must be within 4K space (offset only 12 bits) of program counter.
Hence the data must be located in close proximity of code.

9. This program intends to copy four 32-bit words from Table1 address to Table2 address. It
uses R1 as source address pointer, R2 as destination address pointer and R12 as loop
counter. One more spare address pointer R3 is initialized to Table3 but not used.

10. Note the code uses R0 as data register which receives data from source memory and
sends to destination memory. LDR mnemonic is used here in register-indirect mode. The
indirection is shown by using pointer register inside [].

11. A loop is executed which reads/writes one 32-bit word. This is executed 4 times.

12. Each time the address pointers are incremented by 4 and the loop counter is decremented
by 1. This is a classical and primitive memory copy operation, prevalent in all processors at
assembly language level.

13. As before there is an infinite loop at the end of task, to stop execution from running out of
our code.

14. After the infinite loop ALIGN directive ensures that data area begins at 4 byte address
boundary. You may comment out ALIGN statement and see what kind of error the compiler
may generate.

15. BUILD the target till there are no errors and no warnings. Check that a list file called
data_movement_1.lst” is created. This file contains source program in assembly language as
well as machine code generated by assembler. It also lists various symbols used by the
program. They are labels or names of data variables and addresses.

16. Start debugging session. See the code in disassembly window that it begins with address
0x00000008. Now open the Memory Window 1, if not already open and type 0x08 in its
window to display contents of program area from location 8. Note that first instruction’s 32-
bit code in memory window and .lst file are same except the order of bytes.

17. Check in memory window that address 002C contains 4 bytes of table1 data of source
area - 0x0123, 0x4567, 0x89AB, 0xCDEF. Also check that memory area 003C which is Table2
or destination area, contains 00 all over. As the program will be executed, 4 bytes from
source area will get copied in destination area.
18. As single stepping proceeds, check that address of Table1 i.e. 0x2C is loaded in R1 and
similarly addresses of Table2 (0x3C) and Table3 (0x4C) are loaded in R2 and R3 respectively.
We have not explicitly mentioned the value of these addressees. Wherever the code ends,
the data gets stored from that point and that address is allocated to Table1, Table2 and
Table3. So data storing address is decided by length of program.

19. R0 is used as a data holding register and it is loaded from memory location pointed by
register R1. This is implemented by instruction LDR R0, [R1]. The square brackets indicate
indirection or register-indirect mode.

20. Instruction STR R0, [R2] stores the contents of data register R0 using R2 as address
pointer. Check whether destination area pointed by R2 i.e. 0x3C contents have changed. You
would notice that they are not. This is because it is a READONLY area and any write in that
memory area will go waste.

21. This happened because we have set up Table2 in code area which is usually a part of ROM
and which cannot be written into at run time. Note that the program will run completely as
planned except that actual memory write or store operation in Table2 will not truly happen.

22. We will next take up another method of declaring data area that will allow us read write
access to Table2 and fill into it successfully.

Part II: Defining separate areas for code, data and stack in Keil Assembler

23. Refer to following link on Rochester Institute of Technology. The file “exercise_01.pdf “
describes setting up the Keil MDK and loading and running first assembly program of copying
words from ROM area (called constants) to RAM area (called variable storage or data area).
The link also provides a template containing declarations for code, constants, stack and
read/write data areas. The file of name ”template.s” provides an excellent format which may
be used in your future programs.

http://www.ce.rit.edu/studentresources/reference_materials/cmpe250/

24. Note the structure of the “template.s” program and various areas it defines:
 Vector declaration
 Stack size declaration
 Code area and reset_handler declaration
 Subroutine area or space
 Constants area
 Stack area
 Read write data area

25. You may not need all of the above in your code but it good to follow the template
completely so that nothing of critical importance is missed out.
26. Remove all files from above project and close all open files in editor area. Add file
“data_movement_2.s”. Open the file and see its contents. This file is copied from first
program given from “exercise_01.pdf “.
27. Note the program contains new format of instruction LDR R2, =ConstData. This loads 32
bit address of label ConstData (0xE4) in register R2, irrespective of its address in memory.
The constraint of 4K proximity instruction ADR is no longer applicable here. This is more
evident when we use similar instruction LDR R0, =VarData.

28. Note that label VarData is situated in RAM area and it is hundreds of Mbytes away from
code area. Now we are free to locate our memory blocks anywhere in physical addresses as
available in the given MCU chip.

29. Compile the project and examine the .lst file and note the addresses of various labels.
These addresses are not final and linker will shift them later before debugging begins.

30. Run the code. Note that our program or code begins with address 0. Open Memory
Window 1 and see the contents from address 0. Check that ConstData can be viewed from its
address 0xE4.

31. As you single step, you will notice that address of constants i.e. ConstData = 0x000000E4
is loaded in source pointer register R2. This data will be copied into RAM area.

32. As you step further, you will notice that address of VarData is 0x20000000 and that is
loaded in R0.

33. Open second window called Memory 2. Type 0x20000000 in its windows to show contents
of data area in RAM. Initially you would see all 0s there. After the code is executed, you
would see 2 words (8 bytes) copied there.

34. Single step through the code. As you execute STR R1, [R0, #i] instruction, you would see
4 bytes or 1 word copied into RAM area. First time i is taken as 0 and second time i is taken
as 4. The program runs completely and there is no access permission error as before.

35. The program provides 4 words in source and only 2 words in destination so it runs the
copy operation twice. The LDR/ STR use adding an offset of either 0 or 4 to address before
performing memory access. After copying 4+4= 8 bytes, it increments source address
pointer by 8.

36. This format of specifying various memory areas will be used in all subsequent programs.

Part III: Using Primitive Addressing Modes to Fill Memory Area with known Data

37. Remove previous files from the project. Add file “fill_array1.s” provided to you in this
folder.

38. Study the code and note that this program has 3 data arrays called Table1 (64 bytes),
Table2 (64 bytes) and Table3 (256 bytes). In this program we will use only Table1.
39. This program uses two pointer registers holding addresses of memory location. They are
R0 which holds base value 0x2000000 and second register is R1 which contains offset from
base address. The total address at any time is (R0+R1). We set base address R0 once and as
we progress through entries, we increment offset address by 4 (it is a 4-byte word). This
arrangement allows us to access various lists or arrays to fill in by just specifying starting
address in R0. Register R3 is a down-counter initialized to 16 since we wish to fill 16 words
(64 bytes) of Table1.

40. Register R2 contains constant. We will increment it by 0x10000000 initially so that each
one of the 16 locations has different values filled. This increment can be any large 32-bit
value also. Change this value to 1 and see the effect on data filled up.

41. Note that the code has two parts – some initialization part and a loop part. Loop runs for
16 iterations. In each iteration, one 32-bit word constant is stored.

42. Build target and open Memory Window to show data area 0x20000000. See that it is all
filled up with zero initially.

43. Single step code and see the values in register after each instruction.

44. See that after every STR R2, [R0, R1] instruction, 4 bytes in Data area change as per
value in register R2. Also note that offset address register R1 is incremented by 4 and
counter register R3 is decremented by 1.

45. After 16 loops, the program terminates successfully.

46. NOP instruction is provided where you can conveniently set the breakpoint and execute at
full speed.

Part IV: Using Auto-Increment Indexed Mode to Fill Memory Area with known Data

47. Start uV5. Remove previous files from the project. Add file “fill_array2.s” provided to you
in this folder. Study the code.

48. The instruction used is STR R2, [R0, #4]! . It means first increment (pre-increment)
address pointer register or base register R0, by offset (4) and then store the data of register
R2 in memory location pointed by R0.

49. Since we wish to begin storing from Table1, we have to initialize pointer register R0, per
force, by (Table1-offset) i.e. Table1-4.

50. Thus whenever we will be using pre-indexed auto increment mode, we must initialize our
base register to a value beginning (address – offset). In our example this is (0x20000000–4).

51. Register R2 modifies or increments data. Register R3 is loop counter.


52. Since this addressing mode modifies base register itself after every use, there is no need
for a separate offset register and incrementing it by 4 so register R3 is free now.

53. Notice how small and simplified the program has become due to auto indexing.

54. Execute the program. It will work in identical manner to previous program with a
difference that it will take fewer cycles to complete task.

55. Note that initially R0 is loaded with 0x1FFFFFFC and not 0x2000000.

56. Run it once to see 16 words filled.

57. Change the code line ADDS R2, #1 to ADDS R2, #0x1000 and see that the new data
which is filled is 0000,1000,2000,3000 in hex and so on. Try with an increment of
0x10000000 or higher value in above instruction and check the sequence of values filled.

58. Now we will do the same task of filling memory using post-index auto increment mode.

59. Remove all files from project and add “fill_array3.s” file. Study the code.

60. The instruction used in this code is STR R2, [R0],#4. This instruction uses post-indexing
auto-increment. It uses the address pointer R0 and store data in memory. Then it adds offset
4 specified as immediate operand to pointer register R0 or auto-increment it. Note that there
is no separate or specific ‘!’ delimiter to indicate auto-incrementing in this mode. It is hidden.

61. Since we are first storing and then incrementing the pointer, the starting address is now
Table1 itself. We need not subtract offset (4) from it initially. This is more intuitive and
elegant.

62. Run the code with different offset or increment value in ADDS R2, #1. See that arithmetic
series is modified accordingly.

Part V: Using Auto-Increment Indexed Mode to Copy Block of Memory

63. Start uV5. Remove previous files from the project. Add file “fill_copy_1.s” provided to
you in this folder. Study the code.
64. The program has two parts. First part fills up source area Table1 with a known data set
and second part copies it into another area Table2.
65. The usage of various registers is as follows:
 R0 - source index register
 R1 - destination index register
 R2 - data holding register
 R3 - loop counting register
66. R0 and R1 are initialized to Table1-4 and Table2-4 respectively since we intend to use
pre-indexed auto increment mode.
67. Data is read from source area using R0 register into data register R2. R0 gets
incremented by 4 so it is ready for next iteration.

68. Then contents of R2 are stored in destination area pointed by R1. R1 also gets auto
incremented by 4 and is ready for next iteration.

69. Counter is decremented and loop runs till it reaches 0. Since counter was initialized to 16,
the loop has 16 iterations.

70. Build target. You may set breakpoint at the NOP after fill portion and run program at full
speed using key F5.Note that 64 bytes of data is filled up from 0x20000000.

71. Now watch area pointed by Table2 i.e. 0x40000040. As the program executes each
iteration of the loop, one 4-byte word will get copied into this area.

72. Auto increment mode saves two instructions to increment both pointer registers.

73. Now we shall repeat the fill and copy takes using post-indexed auto-increment mode.

74. Remove previous files from the project. Add file “fill_copy_1A.s” provided to you in this
folder. Study the code.

75. Rest of the operation is same except that pointers are initialized to table1 and Table2 and
there is no need to subtract the offset as in pre-indexed mode.

Part VI: Using Multiple Register Transfer Instructions Mode to Copy Block of Memory

76. Start uV5. Remove previous files from the project. Add file “fill_copy_2.s” provided to you
in this folder. Study the code.

77. The program has two parts. First part fills up source area Table1 with a known data set
and second part copies it into another area Table2.

78. The usage of various registers is as follows:


 R0 - source index register
 R1 - destination index register
 R2 to R9 - eight registers transfer data in one single instruction
 R0 and R1 are initialized to Table1-4 and Table2-4 respectively since we intend to use pre-
indexed auto increment mode
 There is no loop counter since we need to do this twice only.

79. Data is read from source area using R0 register into EIGHT data registers R2 to R9,
sequentially and automatically. The instruction used is LDMIA R0! , {R2-R9}. Note that
addressing mode is IA i.e. Increasing After which means first perform memory operation and
THEN increment register. Here, R0 gets incremented by 4*8 or 32, so it is ready for next
iteration.
80. Then contents of EIGHT registers R2 to R9, are stored in 8 destination words pointed by
R1. The instruction used is STMIA R1! , {R2-R9}. R1 behaves exactly like R0 and also gets
auto incremented by 4*8 or 32 and is ready for next iteration.

81. This set of Load Store Multiple Registers is executed one more times so that 8 more words
are copied.

82. If we need to do it more times than 2 then perhaps it is a good idea to encase one load
store pair in a loop.

83. Build the target and open Memory Window to observe source and destination areas. First
fill up the source area.

84. Single step the code for copy portion. Note that as LDMIA R0!, {R2-R9} instruction is
executed, 8 registers R2 to R9 suddenly get new values from memory. When next instruction
STMIA R1! , {R2-R9} is executed, suddenly 8 words get stored in destination area.

85. Note that 4 instructions executed together copy 16 words or 64 bytes. This is the power of
multiple register transfer instruction.

86. There are many more modes of multiple register transfer instruction in which
decrementing the address pointer is also allowed. See the text book for more details and
practice.

DIY: 1. Write a program to copy backwards from higher location address to lower
location address for both pointers (LDMDA & STMDA).

2. Modify the above so that source pointer reads from lower address to higher address
while destination pointer writes from higher address to lower address.

3. What do following instructions do?

STMFD R13! , {R2-R9}

…….

..…..

LDMFD R13! , {R2-R9}

Hint: STMFD stands for “full descend” and is identical to STMDB. (why?)

4. Understand the complete philosophy and application of ‘Increment/Decrement’,


‘Before/After’ ‘Full/Empty’ and ‘ascending/descending’ words on creating addressing
modes.

------------------------ End of Experiment #2 ---------------------------------------------

You might also like