Computer Design

University of Cambridge Computer Laboratory

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

        EXPORT  divasm
divasm                          ; enters with a and b in registers a1 and a2
        MOV     a3,#1           ; a3=Rcnt from lecture
        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
        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



C  Test Code and Divide Routine


/* 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 */

  do {
    if((a-b)>=0) {
  } while(t!=0);
  return r;

int main( int argc, char **argv )
  int i,j,k;
  for(i=1; i<64; i+=3) {
    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

        EXPORT  divc
        MOV      a3,#1
        TST      a2,#&40000000
        BNE      |L00001c.J5.divc|
        MOV      a2,a2,LSL #1
        MOV      a3,a3,LSL #1
        TST      a2,#&40000000
        BEQ      |L00000c.J4.divc|
        MOV      a4,#0
        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
        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
        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}
        DCB     &45,&52,&52,&4f
        DCB     &52,&21,&21,&21
        DCB     &20,&20,&20,&00
        DCB     &2e,&2e,&2e,&2e
        DCB     &63,&6f,&72,&72
        DCB     &65,&63,&74,&00
        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
        DCB     &20,&3d,&20,&25
        DCB     &34,&64,&20,&25
        DCB     &73,&0a,&00,&00

        AREA |C$$data|,DATA



Back to the main index