mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-21 06:26:49 +08:00
122 lines
2.2 KiB
ArmAsm
122 lines
2.2 KiB
ArmAsm
.global main
|
|
.align 2
|
|
|
|
/* Walkies - a silly animation using four characters on the Linux
|
|
console. This program demonstrates low level IO (write()) and
|
|
is written in the form of an infinite loop (i.e. ^C or kill will
|
|
be required to halt the program).
|
|
*/
|
|
|
|
counter .req w20
|
|
delta .req w21
|
|
.equ MAX_COLUMN, 60
|
|
.equ NUM_CHARS, 4
|
|
|
|
.section .rodata
|
|
|
|
CHARS: .asciz "|/_\\"
|
|
TRM: .asciz " \r"
|
|
|
|
.text
|
|
|
|
main: stp x29, x30, [sp, -16]!
|
|
stp x20, x21, [sp, -16]!
|
|
|
|
mov counter, wzr
|
|
mov w0, wzr
|
|
mov delta, 1
|
|
|
|
0: bl Pad
|
|
bl Emit
|
|
bl Terminator
|
|
add counter, counter, delta
|
|
mov w0, MAX_COLUMN
|
|
cmp w0, counter
|
|
bne 1f
|
|
neg delta, delta
|
|
b 2f
|
|
1: cbnz counter, 2f
|
|
neg delta, delta
|
|
|
|
2: ldr x0, =usec
|
|
ldr w0, [x0]
|
|
bl usleep
|
|
b 0b
|
|
|
|
ldp x20, x21, [sp], 16
|
|
ldp x29, x30, [sp], 16
|
|
mov w0, wzr
|
|
ret
|
|
|
|
/* Terminator - outputs "\r " - notice the space after
|
|
the carriage return.
|
|
*/
|
|
|
|
Terminator:
|
|
stp x29, x30, [sp, -16]!
|
|
mov w0, 1 // 1 is stdout
|
|
ldr x1, =TRM // Pointer to string
|
|
mov w2, 2 // 2 characters being printed
|
|
bl write
|
|
ldp x29, x30, [sp], 16
|
|
ret
|
|
|
|
/* Emit - puts out the symbol derived from counter.
|
|
*/
|
|
|
|
Emit: stp x29, x30, [sp, -16]!
|
|
mov w0, counter
|
|
mov w1, NUM_CHARS
|
|
bl mod
|
|
ldr x1, =CHARS
|
|
add x1, x1, x0
|
|
mov w0, 1
|
|
mov w2, 1
|
|
bl write
|
|
ldp x29, x30, [sp], 16
|
|
ret
|
|
|
|
|
|
/* Pad - prints w0 spaces to the console.
|
|
*/
|
|
|
|
Pad: stp x29, x30, [sp, -16]!
|
|
str delta, [sp, -16]!
|
|
mov w21, wzr
|
|
|
|
1: ldr x1, =buff
|
|
mov w2, ' '
|
|
strb w2, [x1] // ' ' is pointed to by x1
|
|
mov w0, 1 // 1 is stdout
|
|
mov w2, 1 // emitting 1 byte
|
|
bl write
|
|
add w21, w21, 1
|
|
cmp w21, counter
|
|
blt 1b
|
|
|
|
ldr delta, [sp], 16
|
|
ldp x29, x30, [sp], 16
|
|
ret
|
|
|
|
/* mod(a, b) - implements a % b - AARCH64 lacks a mod instruction.
|
|
A strange place to economize, but there you have it.
|
|
|
|
a comes to us in x0
|
|
b comes to us in x1
|
|
method:
|
|
* integer divide a by b
|
|
for example - 5 % 3 would need 5 // 3 yielding 1
|
|
* multiply result by b
|
|
1 * 3 is 3
|
|
* subtract result from a
|
|
5 - 3 is 2 and that's our return value.
|
|
*/
|
|
|
|
mod: sdiv x2, x0, x1 // x2 gets a // b
|
|
msub x0, x2, x1, x0 // x0 gets a - a // b * b
|
|
ret
|
|
|
|
.data
|
|
buff: .space 4
|
|
usec: .int 75000
|
|
|