# Computer Design

## 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);

|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]

|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
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
BL       divasm
MOV      v4,a1
MOV      a2,v2
MOV      a1,#&d2
BL       divc
MOV      v3,a1
MOV      a1,v2
MOV      a2,#&d2
BL       __rt_sdiv
MOV      v1,a1
TEQ      a1,v4
MOV      a3,v4
MOV      a2,v2
BL       _printf
TEQ      v1,v3
MOV      a2,v3
BL       _printf
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
```

Back to the main index