.text .global _start @@@ Check if the zero-terminated ASCII string in [r0], @@@ which should contain a decimal number, has a @@@ matching check digit. Zero flag set if true, @@@ check digit returned in r0. damm: mov r1,#0 @ R1 = interim digit ldr r2,=3f @ R2 = table base address 1: ldrb r3,[r0],#1 @ Load byte tst r3,r3 @ Zero yet? beq 2f @ If so, stop sub r3,r3,#'0 @ Subtract ASCII 0 lsl r1,r1,#1 @ Table lookup add r1,r1,r1,lsl#2 @ R3 = R1*10 + R3 add r3,r1,r3 ldrb r1,[r2,r3] @ R1 = new interim digit b 1b @ Next value 2: movs r0,r1 @ Set flag according to r0. bx lr 3: .byte 0,3,1,7,5,9,8,6,4,2 @ Since the table is constant, .byte 7,0,9,2,1,5,4,8,6,3 @ it can be stored as part of .byte 4,2,0,6,8,7,1,3,5,9 @ the subroutine. .byte 1,7,5,0,9,8,3,4,2,6 @ This way the OS will even mark .byte 6,1,2,3,0,4,5,9,7,8 @ it as read-only, so we can .byte 3,6,7,4,2,0,9,5,8,1 @ be sure nothing changes it. .byte 5,8,6,9,7,2,0,1,3,4 .byte 8,9,4,5,3,6,2,0,1,7 .byte 9,4,3,8,6,1,7,2,0,5 .byte 2,5,8,1,4,3,6,7,9,0 .align 4 @ Instructions must be word-aligned @@@ Grab the argument from the command line, and see @@@ if it matches. _start: pop {r0} @ Is there even an argument? cmp r0,#2 movne r7,#1 @ If not, exit immediately swine #0 add sp,sp,#4 @ Discard program name pop {r0} @ Grab argument bl damm @ Check if it matches ldreq r1,=pass @ If yes, say 'pass' ldrne r1,=fail @ If not, say 'fail' mov r0,#1 @ Print string to stdout mov r2,#5 @ Both are 5 characters mov r7,#4 @ Write syscall = 4 swi #0 mov r0,#0 @ Exit mov r7,#1 swi #0 pass: .ascii "Pass\n" fail: .ascii "Fail\n"