Category:ARM Assembly: Difference between revisions
Puppydrum64 (talk | contribs) No edit summary |
Puppydrum64 (talk | contribs) Added better examples. |
||
Line 15:
Checking for condition codes isn't just limited to branching on the ARM. Almost every instruction can be made conditional. If the condition is not met, the opcode will have no effect. This saves a lot of cycles that would be spent branching just to execute a single instruction.
Compare the following snippets of code. The first is written in 8086 Assembly, the second in ARM. Both do the same thing, but ARM can do it without branching.
<lang ARM Assembly>addeq r0,r0,r1 ;if the last math operation had an answer of zero, add r0 to r1 and store the result in r0.</lang>▼
[[Category:Assembly]]▼
<lang asm>mov ax, word ptr [ds:TestData] ;dereference the pointer to TestData and store the value contained within that address into ax
add ax,1 ;add 1 to ax
jo OverflowSet ;the addition caused an overflow, jump to this label.
ret ;return from subroutine
OverflowSet:
sub ax,1 ;rollback the previous addition.
ret ;return from subroutine.</lang>
The same code translated to ARM doesn't need to branch:
<lang ARM Assembly>mov r1,#TestData ;get the address of TestData
ldr r0,[r1] ;load the 32-bit value stored at TestData into r0
adds r0,r0,#1 ;add 1 to r0 and store the result in r0, updating the flags accordingly.
subvs r0,r0,#1 ;subtract 1 from r0 and store the result in r0, <i>only if the overflow flag was set.</i></lang>
If your code does one thing when a flag is set and another when that same flag is clear, the ARM can do both without having to branch at all.
<lang ARM Assembly>;ARM ASSEMBLY
mov r1,#TestData ;get the address of TestData
ldrs r0,[r1] ;load the 32-bit value stored at TestData into r0, updating the flags accordingly.
▲
subne r0,r0,r2 ;if r0 doesn't equal zero, subtract r2 from r0 and store the result in r0.</lang>
The equivalent in x86 would take at least one branch, maybe 2 depending on the outcome:
<lang asm>;x86 ASSEMBLY
mov ax, word ptr [ds:TestData]
cmp ax,0
bne subtract_bx
add ax,bx
jmp done
subtract_bx:
sub ax,bx
done:</lang>
===Setting Flags===
The flags, or condition codes, are only set by instructions that end in an "s," or by compare commands such as <code>CMP</code>. This lets you "preserve" the processor's state after an important calculation, but do some other things before execution branches depending on the result of that calculation. On any other processor, the calculation that determines whether a branch occurs MUST happen JUST before that branch statement or the branch will be taken based on the wrong data.
<lang ARM Assembly>cmp r0,r1 ;compare r0 to r1
ldr r2,[r3] ;load r2 from the address stored in r3
ldr r3,[r4] ;load r3 from the address stored in r4
bne myLabel ;branch to myLabel if the result of "cmp r0,r1" was not equal to zero.</lang>
Most processors would have to push and pop the condition code register between the compare and the branch. Otherwise, the act of loading <code>r2</code> and <code>r3</code> would affect the outcome of the branch. Not so on the ARM!
▲[[Category:Assembly]]
|
Revision as of 16:22, 7 September 2021
This programming language may be used to instruct a computer to perform a task.
See Also: |
|
---|
The ARM architecture is widely used on mobile phones and tablets. It falls under the category of RISC (Reduced Instruction Set Computer) processors, which means it has fewer opcodes than a CPU such as those in the x86 family. However, it makes up for this with its speed. The ARM and its variants are used in many well-known systems such as the Raspberry Pi, Nintendo DS, iPad, and more.
Barrel Shifter
The ARM can add a bit shift or rotate to one of its operands at no additional cost to execution time or bytecode. If the operand being shifted is a register, the value of that register is not actually changed. The shift or rotate only applies during that instruction.
<lang ARM Assembly>add r0,r0,r1 lsl 2 ;shift r1 left 2 bits, add r0 to r1, store the result in r0. r1 is unchanged after this instruction</lang>
Separate Destination for Math
With the x86, 68000, and other similar processors, arithmetic functions take two operands: the source and the destination. Anytime you add two numbers, one of them gets changed. This is not the case with the ARM. The destination can be a third register that isn't involved in the arithmetic whatsoever!
<lang ARM Assembly> add r3,r2,r1 ;add r2 to r1 and store the result in r3. r1 and r2 are unchanged.</lang>
Conditional Opcodes
Checking for condition codes isn't just limited to branching on the ARM. Almost every instruction can be made conditional. If the condition is not met, the opcode will have no effect. This saves a lot of cycles that would be spent branching just to execute a single instruction.
Compare the following snippets of code. The first is written in 8086 Assembly, the second in ARM. Both do the same thing, but ARM can do it without branching.
<lang asm>mov ax, word ptr [ds:TestData] ;dereference the pointer to TestData and store the value contained within that address into ax add ax,1 ;add 1 to ax jo OverflowSet ;the addition caused an overflow, jump to this label. ret ;return from subroutine
OverflowSet: sub ax,1 ;rollback the previous addition. ret ;return from subroutine.</lang>
The same code translated to ARM doesn't need to branch: <lang ARM Assembly>mov r1,#TestData ;get the address of TestData ldr r0,[r1] ;load the 32-bit value stored at TestData into r0 adds r0,r0,#1 ;add 1 to r0 and store the result in r0, updating the flags accordingly. subvs r0,r0,#1 ;subtract 1 from r0 and store the result in r0, only if the overflow flag was set.</lang>
If your code does one thing when a flag is set and another when that same flag is clear, the ARM can do both without having to branch at all.
<lang ARM Assembly>;ARM ASSEMBLY mov r1,#TestData ;get the address of TestData ldrs r0,[r1] ;load the 32-bit value stored at TestData into r0, updating the flags accordingly. addeq r0,r0,r2 ;if r0 equals zero, add r2 to r0 and store the result in r0. subne r0,r0,r2 ;if r0 doesn't equal zero, subtract r2 from r0 and store the result in r0.</lang>
The equivalent in x86 would take at least one branch, maybe 2 depending on the outcome: <lang asm>;x86 ASSEMBLY
mov ax, word ptr [ds:TestData] cmp ax,0 bne subtract_bx add ax,bx jmp done
subtract_bx:
sub ax,bx
done:</lang>
Setting Flags
The flags, or condition codes, are only set by instructions that end in an "s," or by compare commands such as CMP
. This lets you "preserve" the processor's state after an important calculation, but do some other things before execution branches depending on the result of that calculation. On any other processor, the calculation that determines whether a branch occurs MUST happen JUST before that branch statement or the branch will be taken based on the wrong data.
<lang ARM Assembly>cmp r0,r1 ;compare r0 to r1 ldr r2,[r3] ;load r2 from the address stored in r3 ldr r3,[r4] ;load r3 from the address stored in r4 bne myLabel ;branch to myLabel if the result of "cmp r0,r1" was not equal to zero.</lang>
Most processors would have to push and pop the condition code register between the compare and the branch. Otherwise, the act of loading r2
and r3
would affect the outcome of the branch. Not so on the ARM!
Subcategories
This category has the following 3 subcategories, out of 3 total.
@
- ARM Assembly Implementations (empty)
- ARM Assembly User (16 P)
Pages in category "ARM Assembly"
The following 200 pages are in this category, out of 252 total.
(previous page) (next page)A
- A+B
- Abbreviations, automatic
- Abbreviations, easy
- Abbreviations, simple
- ABC problem
- Abelian sandpile model
- Abelian sandpile model/Identity
- Abundant odd numbers
- Abundant, deficient and perfect number classifications
- Achilles numbers
- Ackermann function
- Additive primes
- Address of a variable
- ADFGVX cipher
- AKS test for primes
- Align columns
- Aliquot sequence classifications
- Almkvist-Giullera formula for pi
- Almost prime
- Amicable pairs
- Anagrams
- Anagrams/Deranged anagrams
- Angle difference between two bearings
- Animation
- Anti-primes
- Arithmetic numbers
- Arithmetic/Integer
- Array concatenation
- Array length
- Arrays
- ASCII art diagram converter
- Associative array/Creation
- Averages/Median
- AVL tree
B
C
- Caesar cipher
- Call a foreign-language function
- Call a function
- Character codes
- Check that file exists
- Chinese remainder theorem
- Code Golf: Code Golf
- Colour pinstripe/Display
- Command-line arguments
- Comments
- Compare length of two strings
- Compound data type
- Conditional structures
- Conway's Game of Life
- Copy a string
- Count in factors
- Count in octal
- Count occurrences of a substring
- Create a file
- Create a two-dimensional array at runtime
- Create an HTML table
- Create an object at a given address
D
F
H
I
L
- Letter frequency
- Literals/Integer
- Literals/String
- Logical operations
- Long multiplication
- Loops/Break
- Loops/Do-while
- Loops/Downward for
- Loops/For
- Loops/For with a specified step
- Loops/Increment loop index within loop body
- Loops/Infinite
- Loops/N plus one half
- Loops/Nested
- Loops/While
- Loops/With multiple ranges
- Lucas-Lehmer test
- Luhn test of credit card numbers
P
R
S
- Sattolo cycle
- Sequence of primes by trial division
- SHA-1
- SHA-256
- SHA-256 Merkle tree
- Show ASCII table
- Sieve of Eratosthenes
- Singly-linked list/Element definition
- Singly-linked list/Element insertion
- Singly-linked list/Traversal
- Sleep
- Solve the no connection puzzle
- Sort an array of composite structures
- Sort an integer array
- Sort disjoint sublist
- Sorting algorithms/Bead sort
- Sorting algorithms/Bogosort
- Sorting algorithms/Bubble sort
- Sorting Algorithms/Circle Sort
- Sorting algorithms/Cocktail sort
- Sorting algorithms/Cocktail sort with shifting bounds
- Sorting algorithms/Comb sort
- Sorting algorithms/Counting sort
- Sorting algorithms/Gnome sort
- Sorting algorithms/Heapsort
- Sorting algorithms/Insertion sort