| |||
| Home > Basic Assembly Language Programming > Load and store multiple register instructions > Block copy with LDM and STM | |||
Example 5.10 is an ARM
code routine that copies a set of words from a source location to
a destination by copying a single word at a time. It is supplied
as word.s in the examples\asm subdirectory
of the toolkit. Refer to Code examples for instructions on how to assemble,
link, and execute the example.
Example 5.10. : Block copy
AREA Word, CODE, READONLY ; name this block of code. num EQU 20 ; set number of words to be copied. ENTRY ; mark the first instruction to call start LDR r0, =src ; r0 = pointer to source block LDR r1, =dst ; r1 = pointer to destination block MOV r2, #num ; r2 = number of words to copy wordcopy LDR r3, [r0], #4 ; load a word from the source and STR r3, [r1], #4 ; store it to the destination. SUBS r2, r2, #1 ; decrement the counter. BNE wordcopy ; ... copy more. stop MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; Angel semihosting ARM SWI AREA BlockData, DATA, READWRITE src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4 dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 END
This module can be made more efficient by using LDM and STM for
as much of the copying as possible. Eight is a sensible number of
words to transfer at a time, given the number of registers that
the ARM has. The number of eight-word multiples in the block to
be copied can be found (if r2 = number of words to be copied) using:
MOVS r3, r2, LSR #3 ; number of eight word multiples
This value can be used to control the number of iterations through a loop that copies eight words per iteration. When there are less than eight words left, the number of words left can be found (assuming that r2 has not been corrupted) using:
ANDS r2, r2, #7
Example 5.11 lists
the block copy module rewritten to use LDM and STM for copying.
Example 5.11.
AREA Block, CODE, READONLY ; name this block of code.
num EQU 20 ; set number of words to be copied.
ENTRY ; mark the first instruction to call.
start
LDR r0, =src ; r0 = pointer to source block
LDR r1, =dst ; r1 = pointer to destination block.
MOV r2, #num ; r2 = number of words to copy.
MOV sp, #0x400 ; Set up stack pointer (r13).
blockcopy MOVS r3,r2, LSR #3 ; Number of eight word multiples.
BEQ copywords ; Less than eight words to move?
STMFD sp!, {r4-r11} ; Save some working registers.
octcopy LDMIA r0!, {r4-r11} ; Load 8 words from the source
STMIA r1!, {r4-r11} ; and put them at the destination.
SUBS r3, r3, #1 ; Decrement the counter.
BNE octcopy ; ... copy more.
LDMFD sp!, {r4-r11} ; Don't need these now - restore
; originals.
copywords ANDS r2, r2, #7 ; Number of odd words to copy.
BEQ stop ; No words left to copy?
wordcopy LDR r3, [r0], #4 ; load a word from the source and
STR r3, [r1], #4 ; store it to the destination.
SUBS r2, r2, #1 ; Decrement the counter.
BNE wordcopy ; ... copy more.
stop MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SWI 0x123456 ; Angel semihosting ARM SWI
AREA BlockData, DATA, READWRITE
src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
END