51 lines
1.6 KiB
Plaintext
51 lines
1.6 KiB
Plaintext
.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"
|