Divide Code Example for Lecture 4
At the end of lecture 2 a code example was given to perform integer
division. Below is a copy of the assembler routine,
a simple C test routine with a similar divide
routine also witten in C, and the assembler output
from compiling this code.>
Assembler Routine
; divide function written in ARM assembler
; signature: int divasm(int a, int b);
AREA |C$$code|, CODE, READONLY
|x$codeseg|
EXPORT divasm
divasm ; enters with a and b in registers a1 and a2
MOV a3,#1 ; a3=Rcnt from lecture
divasm1
CMP a2,#0x80000000 ; shift a2 left until top bit set
CMPCC a2,a1 ; ...or a2>a1
MOVCC a2,a2,ASL#1 ; shift a2 left if required
MOVCC a3,a3,ASL#1 ; shift a3 left if required
BCC divasm1 ; repeat whilst more shifting required
MOV ip,#0 ; ip used to store result
divasm2
CMP a1,a2 ; test for possible subtraction
SUBCS a1,a1,a2 ; subtract if a1>a2
ADDCS ip,ip,a3 ; put relivant bit into result
MOVS a3,a3,LSR#1 ; shift control bit
MOVNE a2,a2,LSR#1 ; halve unless finished
BNE divasm2 ; loop if there is more to do
MOV a1,ip ; return result in register a1
MOV pc,lr ; return from the subroutine
|x$dataseg|
END
C Test Code and Divide Routine
#include
/* Simple test program for divasm.s and a C equivalent */
/* compile using 'armcc -li testdiv.c divasm.s */
/* Simon Moore */
extern int divasm(int a, int b);
int divc(int a,int b)
{
int r;
int t=1;
while( (b&0x40000000) == 0 ) { /* fails if b=0 */
b=b<<1;
t=t<<1;
}
r=0;
do {
if((a-b)>=0) {
a=a-b;
r=r+t;
}
b=b>>1;
t=t>>1;
} while(t!=0);
return r;
}
int main( int argc, char **argv )
{
int i,j,k;
for(i=1; i<64; i+=3) {
j=divasm(1234,i);
k=divc(1234,i);
printf("1234/%2d = %4d %s",i,j,(1234/i)==j ? "....correct" : "ERROR!!! ");
printf(" = %4d %s\n",k,(1234/i)==k ? "....correct" : "ERROR!!! ");
}
return 0;
}
Disassembled Output From Compling the C Routine
; generated by Norcroft ARM C vsn 4.62 (Advanced RISC Machines) [May 04 1994]
AREA |C$$code|, CODE, READONLY
|x$codeseg|
EXPORT divc
divc
MOV a3,#1
TST a2,#&40000000
BNE |L00001c.J5.divc|
|L00000c.J4.divc|
MOV a2,a2,LSL #1
MOV a3,a3,LSL #1
TST a2,#&40000000
BEQ |L00000c.J4.divc|
|L00001c.J5.divc|
MOV a4,#0
|L000020.J8.divc|
SUBS ip,a1,a2
MOVPL a1,ip
ADDPL a4,a4,a3
MOV a2,a2,ASR #1
MOVS a3,a3,ASR #1
BNE |L000020.J8.divc|
MOV a1,a4
MOV pc,lr
IMPORT __rt_stkovf_split_small
IMPORT divasm
IMPORT __rt_sdiv
IMPORT _printf
EXPORT main
main
MOV ip,sp
STMDB sp!,{v1-v4,fp,ip,lr,pc}
SUB fp,ip,#4
CMP sp,sl
BLLT __rt_stkovf_split_small
MOV v2,#1
|L000058.J4.main|
MOV a2,v2
MOV a1,#&d2
ADD a1,a1,#&400
BL divasm
MOV v4,a1
MOV a2,v2
MOV a1,#&d2
ADD a1,a1,#&400
BL divc
MOV v3,a1
MOV a1,v2
MOV a2,#&d2
ADD a2,a2,#&400
BL __rt_sdiv
MOV v1,a1
TEQ a1,v4
ADDNE a4,pc,#L0000dc-.-8
ADDEQ a4,pc,#L0000e8-.-8
MOV a3,v4
MOV a2,v2
ADD a1,pc,#L0000f4-.-8
BL _printf
TEQ v1,v3
ADDNE a3,pc,#L0000dc-.-8
ADDEQ a3,pc,#L0000e8-.-8
MOV a2,v3
ADD a1,pc,#L000108-.-8
BL _printf
ADD v2,v2,#3
CMP v2,#&40
BLT |L000058.J4.main|
MOV a1,#0
LDMDB fp,{v1-v4,fp,sp,pc}
L0000dc
DCB &45,&52,&52,&4f
DCB &52,&21,&21,&21
DCB &20,&20,&20,&00
L0000e8
DCB &2e,&2e,&2e,&2e
DCB &63,&6f,&72,&72
DCB &65,&63,&74,&00
L0000f4
DCB &31,&32,&33,&34
DCB &2f,&25,&32,&64
DCB &20,&3d,&20,&25
DCB &34,&64,&20,&25
DCB &73,&00,&00,&00
L000108
DCB &20,&3d,&20,&25
DCB &34,&64,&20,&25
DCB &73,&0a,&00,&00
AREA |C$$data|,DATA
|x$dataseg|
END
|