180 likes | 319 Views
ARM Movement Instructions. MOV Rd, <op2> ; updates N, Z, C Rd = <op2> MVN Rd, <op2> ; Rd = 0xF..F EOR <op2>. ALU Arithmetic Instructions. ADD Rd, Rn, <op2> ; updates N, Z, V, C Rd = Rn + <op2> SUB Rd, Rn, <op2> Rd = Rn - <op2> MUL Rd, Rm, Rs Rd = Rm * Rs
E N D
ARM Movement Instructions • MOV Rd, <op2> ; updates N, Z, C Rd = <op2> • MVN Rd, <op2> ; Rd = 0xF..F EOR <op2>
ALU Arithmetic Instructions • ADD Rd, Rn, <op2> ; updates N, Z, V, C Rd = Rn + <op2> • SUB Rd, Rn, <op2> Rd = Rn - <op2> • MUL Rd, Rm, Rs Rd = Rm * Rs • CMP Rd, <op2> Flags <= Rd - <op2> (difference lost)
ALU Logical Examples • TST Rd, <op2> Flags <= Rd AND <op2> • TEQ Rd, <op2> Flags <= Rd EOR <op2> • AND Rd, Rn, <op2> Rd = Rn AND <op2> update N, Z, C
ALU Logical Examples • EOR Rd, Rn, <op2> Rd = Rn EOR <op2> • ORR Rd, Rn, <op2> Rd = Rn OR <op2> • BIC Rd, Rn, <op2> ;BIt Clear Rd = Rn AND NOT <op2>
Branch Instructions • B(cond) label PC <= “address” of label if cond is met • BL(cond) label PC <= “address” of label if cond is met, set link register to current PC value
Load Instructions • LDR Rd, <am1> Rd = [address] • LDM(cond){IB|IA|DB|DA}, Rd(!), <regs>{^} “block pop”, ! => update Rd, <“regs> => list of registers ^ => set the S bit
Store Instructions • STR Rd, <am1> [address] = Rd • STM(cond){IB|IA|DB|DA}, Rd(!), <regs>{^} “block push”, ! => update Rd, <“regs> => list of registers ^ => set the S bit
Stack Manipulation • LDM(cond)<am4>, Rd(!), <registers> • STM(cond)<am4>, Rd(!), <registers> LDM:pop STM:push stack, ! => update Rd <registers> => list of registers
Assembler Pseudo-ops • AREA -> chunks of data ($data) or code ($code) • ADR -> load address into a register ADR R0, BUFFER • ALIGN -> adjust location counter to word boundary usually after a storage directive • END -> no more to assemble
Assembler Pseudo-ops • DCD -> defined word value storage area BOW DCD 1024, 2055, 9051 • DCB -> defined byte value storage area BOB DCB 10, 12, 15 • % -> zeroed out byte storage area BLBYTE % 30
Assembler Pseudo-ops • IMPORT -> name of routine to import for use in this routine IMPORT _printf ; C print routine • EXPORT -> name of routine to export for use in other routines EXPORT add2 ; add2 routine • EQU -> symbol replacement loopcnt EQU 5
Assembly Line Format label <whitespace> instruction <whitespace> ; comment label: created by programmer, alphanumeric whitespace: space(s) or tab character(s) instruction: op-code mnemonic or pseudo-op with required fields comment: preceded by ; ignored by assembler but useful to the programmer for documentation All fields are optional.
Example: linking C and assembly language • Add two integers using an assembly language routine, follow the ARM standard for linking routines
C Language Driver Routine #include <stdio.h> /* standard input and output */ #include <stdlib.h> /* standard library */ extern int add2( int I, int j ) ; /* tell the compiler that the routine is not defined here */ Int main( int argc, char * argv[] ) /* entry point to the program */ { int i, j ; /* declare the variable types */ int answer ; i = 5 ; /* give the variables values */ j = 20 ; answer = add2( i, j ) ; /* call the assembly language routine */ printf( “result is: %d\n”, answer ) ; /* print out the answer */ exit( 0 ) ; /* leave the driver program */ }
Assembly Language Routine AREA |add2$code|, CODE, READONLY ; tell the assembler stuff EXPORT add2 ; tell the assembler to show this label to the linker add2 ; the label defining the entry point stmfd sp!, {v1-v6, lr} ; ‘standard’ entry, save registers on the stack add a1, a1, a2 ; do the addition requested ldmfd sp!, {v1-v6, pc} ; put the registers back and go back to caller END ; tell the assembler this is the end of the file Pseudo-op codes: tell the assembler to do something rather than generate code. Above, END, EXPORT, AREA, CODE, READONLY.
Another C to Assembler Example • Add an array of integers in assembly language and print out the total using C language library routine.
C Language Driver #include <stdio.h> #include <stdlib.h> #define ARRAY_SIZE 5 /* set the size of the array */ extern int sumarray( int array[], int size ) ; /* declare the assembly routine */ Int main( int argc, char * argv[] ) { int size = ARRAY_SIZE ; /* as input to the summation routine */ int answer ; int numarray[] = { 1, 2, 3, 4, 5 } ; /* initialize the array */ answer = sumarray( numarray, size ) ; /* call the assembly language routine */ exit( 0 ) ; /* we’re done */ }
Assembly Language Routine AREA |sumarray$code|, CODE, READONLY EXPORT sumarray IMPORT _printf sumarray stmfd sp!, {v1-v6, lr} ; standard entry mov a3, #0 ; set sum to zero Sumloop ldr a4, [a1], #4 ; get element, increment pointer add a3, a3, a4 ; add element to partial sum subs a2, a2, #1 ; one less element bne sumloop ; have we done all? mov v1, a3 ; save sum adr a1, anstext ; get address of message mov a2, a3 ; get sum (for %d parameter) bl _printf ; use the C language routine mov a1, v1 ; return value to C ldmfd sp!, {v1-v6, pc} ; standard exit AREA |sumarray$data|, DATA ; message area anstext DCB “Result of summation = %d\n”, 0 END a1 is pointer to array a2 is number of elements a3 is sum of elements a4 element to add