Start page1 page2 page3 page4 page5 page6 page7 page8 page9 page10
The idea on this page is to make a library of useful subroutines, and in that way make the main program more readable. So we need two assembler files now.
.text
.global _start
.extern _phex
.extern _exit
_start:
mov x0,0x9876
bl _phex
bl _exit
.text
.global _phex
.global _exit
_phex: movz x3,16
adr x2,message
again: ror x0,x0,60
and x1,x0,0xF
cmp x1,10
bge isAtoF
add x1,x1,48
b done
isAtoF: add x1,x1,55
done: strb w1,[x2]
add x2,x2,1
subs x3,x3,1
bne again
mov x0,1
adr x1,message
mov x2,17
mov x8,0x40
svc 0
ret
_exit: mov x0,0
mov x8, 93
svc 0
.data
message: .ascii "****************\n"
user@rpi4:~/work $ as hello3.s -o hello3.o
user@rpi4:~/work $ as lib3.s -o lib3.o
user@rpi4:~/work $ ld hello3.o lib3.o -o hello3
user@rpi4:~/work $ ./hello3
0000000000009876
In lib3.s
we declare two labels to be global, so they can be
seen by the linker, and used in other programs.
I like to name these global names starting with an underscore. It will be easier to see what's wrong when there are errors.
In hello3.s
the global names used are listed as .extern
,
and we just branch to them as we did before. The hello3.s
-program is
quite readable now.
Actually in this assembler there is no need to declare the external
names. Any unknown label is automatically external. Even if you do
declare them .extern
, they are still mentioned in the listing as
UNDEFINED SYMBOLS. This can be different on another system.
And now we don't need to assemble all files — only those that have changed.
Now try this:
mov x0,sp
bl _phex
It might print 0000007FD00802A0, which is where the system
has allocated a stack. sp
is just another name for register x29
.
The value is not the same every time you run the program. The stack is actually supposed to be used in subroutines, for local variables and for the return address.
We are ready to see how subroutines really should be made.
Start page1 page2 page3 page4 page5 page6 page7 page8 page9 page10
2025-06-16