Assembly language programming on the Pi

I just got a new book in my Christmas stocking and started working through it this evening: Raspberry Pi Assembly Language Programming by Stephen Smith, Apress (just published last month).

I'm pretty excited about the prospects. But of course since I wanted to work with the Pi 4B and play with Ubuntu 64-bit Server 19.10 I'm now attempting to translate the 32-bit ARM calls into ARM 64-bit so I'm a glutton for punishment. But I managed to make a hello world program.

.section .text
.global _start
_start:
        mov x0, #1
        ldr x1, =helloworld
        mov x2, #13
        mov x8, #0x40
        svc 0
        mov x0, #0x0
        mov x8, #93
        svc 0

.data
helloworld: .ascii "Hello World!\n"
3 Likes

Assembly Language is still state of the art.
I've done it in former day on the Z80 and the MC68000

1 Like

I originally did it on the 8086 processor (woohoo). I wrote at least two TSRs.

Haven't done that since my mainframe days. Gave it up one I discovered higher level languages.

1 Like

build

#!/bin/sh

if uname -snrvm | grep -q armv7l; then
    echo "32-bit detected"
    BITS=32
else
    echo "64-bit detected"
    BITS=64
fi

as -o helloworld.o helloworld-$BITS.s
ld -o bin/helloworld helloworld.o

helloworld-32.s

.section .text
.global _start
_start:
        mov r0, #1
        ldr r1, =helloworld
        mov r2, #13
        mov r7, #4
        svc 0
        mov r0, #0x0
        mov r7, #1
        svc 0

.data
helloworld: .ascii "Hello World!\n"

So now it works on Ubuntu Server 19.10 64-bit and Raspbian Buster Lite 32-bit with the same project. :wink:

Assembly Language is blindingly Fast to run, execute, so quick it needs a delay in it some times

1 Like

Yep - and the code is quite slim.

Improved makefile version of the build process. Just run make in the folder. The main part of the filename is simply edited at the top and used throughout.

makefile

# -----------------------------------------
PROJECT = upper
# Expected source files: *-32.s and *-64.s
# -----------------------------------------
BITS := $(shell getconf LONG_BIT)
OBJS = $(PROJECT).o
ifdef DEBUG
	DEBUGFLGS = -g
else
	DEBUGFLGS =
endif

%.o : %-$(BITS).s
	as $(DEBUGFLGS) -o $@	$<

$(PROJECT): $(OBJS)
	ld  -o bin/$(PROJECT)	$(OBJS)

On a related note for others, that getconf LONG_BIT command will natively return either 32 or 64 on the command line and is great for programmatically making decisions.

$ getconf -a
LINK_MAX                           65000
_POSIX_LINK_MAX                    65000
MAX_CANON                          255
_POSIX_MAX_CANON                   255
MAX_INPUT                          255
_POSIX_MAX_INPUT                   255
NAME_MAX                           255
_POSIX_NAME_MAX                    255
PATH_MAX                           4096
_POSIX_PATH_MAX                    4096
PIPE_BUF                           4096
_POSIX_PIPE_BUF                    4096
SOCK_MAXBUF                        
_POSIX_ASYNC_IO                    
_POSIX_CHOWN_RESTRICTED            1
_POSIX_NO_TRUNC                    1
_POSIX_PRIO_IO                     
_POSIX_SYNC_IO                     
_POSIX_VDISABLE                    0
ARG_MAX                            2097152
ATEXIT_MAX                         2147483647
CHAR_BIT                           8
CHAR_MAX                           255
CHAR_MIN                           0
CHILD_MAX                          29184
CLK_TCK                            100
INT_MAX                            2147483647
INT_MIN                            -2147483648
IOV_MAX                            1024
LOGNAME_MAX                        256
LONG_BIT                           32
MB_LEN_MAX                         16
NGROUPS_MAX                        65536
NL_ARGMAX                          4096
NL_LANGMAX                         2048
NL_MSGMAX                          2147483647
NL_NMAX                            2147483647
NL_SETMAX                          2147483647
NL_TEXTMAX                         2147483647
NSS_BUFLEN_GROUP                   1024
NSS_BUFLEN_PASSWD                  1024
NZERO                              20
OPEN_MAX                           1024
PAGESIZE                           4096
PAGE_SIZE                          4096
PASS_MAX                           8192
PTHREAD_DESTRUCTOR_ITERATIONS      4
PTHREAD_KEYS_MAX                   1024
PTHREAD_STACK_MIN                  16384
PTHREAD_THREADS_MAX                
SCHAR_MAX                          127
SCHAR_MIN                          -128
SHRT_MAX                           32767
SHRT_MIN                           -32768
SSIZE_MAX                          32767
TTY_NAME_MAX                       32
TZNAME_MAX                         
UCHAR_MAX                          255
UINT_MAX                           4294967295
UIO_MAXIOV                         1024
ULONG_MAX                          4294967295
USHRT_MAX                          65535
WORD_BIT                           32
_AVPHYS_PAGES                      944720
_NPROCESSORS_CONF                  4
_NPROCESSORS_ONLN                  4
_PHYS_PAGES                        999946
_POSIX_ARG_MAX                     2097152
_POSIX_ASYNCHRONOUS_IO             200809
_POSIX_CHILD_MAX                   29184
_POSIX_FSYNC                       200809
_POSIX_JOB_CONTROL                 1
_POSIX_MAPPED_FILES                200809
_POSIX_MEMLOCK                     200809
_POSIX_MEMLOCK_RANGE               200809
_POSIX_MEMORY_PROTECTION           200809
_POSIX_MESSAGE_PASSING             200809
_POSIX_NGROUPS_MAX                 65536
_POSIX_OPEN_MAX                    1024
_POSIX_PII                         
_POSIX_PII_INTERNET                
_POSIX_PII_INTERNET_DGRAM          
_POSIX_PII_INTERNET_STREAM         
_POSIX_PII_OSI                     
_POSIX_PII_OSI_CLTS                
_POSIX_PII_OSI_COTS                
_POSIX_PII_OSI_M                   
_POSIX_PII_SOCKET                  
_POSIX_PII_XTI                     
_POSIX_POLL                        
_POSIX_PRIORITIZED_IO              200809
_POSIX_PRIORITY_SCHEDULING         200809
_POSIX_REALTIME_SIGNALS            200809
_POSIX_SAVED_IDS                   1
_POSIX_SELECT                      
_POSIX_SEMAPHORES                  200809
_POSIX_SHARED_MEMORY_OBJECTS       200809
_POSIX_SSIZE_MAX                   32767
_POSIX_STREAM_MAX                  16
_POSIX_SYNCHRONIZED_IO             200809
_POSIX_THREADS                     200809
_POSIX_THREAD_ATTR_STACKADDR       200809
_POSIX_THREAD_ATTR_STACKSIZE       200809
_POSIX_THREAD_PRIORITY_SCHEDULING  200809
_POSIX_THREAD_PRIO_INHERIT         200809
_POSIX_THREAD_PRIO_PROTECT         200809
_POSIX_THREAD_ROBUST_PRIO_INHERIT  
_POSIX_THREAD_ROBUST_PRIO_PROTECT  
_POSIX_THREAD_PROCESS_SHARED       200809
_POSIX_THREAD_SAFE_FUNCTIONS       200809
_POSIX_TIMERS                      200809
TIMER_MAX                          
_POSIX_TZNAME_MAX                  
_POSIX_VERSION                     200809
_T_IOV_MAX                         
_XOPEN_CRYPT                       
_XOPEN_ENH_I18N                    1
_XOPEN_LEGACY                      1
_XOPEN_REALTIME                    1
_XOPEN_REALTIME_THREADS            1
_XOPEN_SHM                         1
_XOPEN_UNIX                        1
_XOPEN_VERSION                     700
_XOPEN_XCU_VERSION                 4
_XOPEN_XPG2                        1
_XOPEN_XPG3                        1
_XOPEN_XPG4                        1
BC_BASE_MAX                        99
BC_DIM_MAX                         2048
BC_SCALE_MAX                       99
BC_STRING_MAX                      1000
CHARCLASS_NAME_MAX                 2048
COLL_WEIGHTS_MAX                   255
EQUIV_CLASS_MAX                    
EXPR_NEST_MAX                      32
LINE_MAX                           2048
POSIX2_BC_BASE_MAX                 99
POSIX2_BC_DIM_MAX                  2048
POSIX2_BC_SCALE_MAX                99
POSIX2_BC_STRING_MAX               1000
POSIX2_CHAR_TERM                   200809
POSIX2_COLL_WEIGHTS_MAX            255
POSIX2_C_BIND                      200809
POSIX2_C_DEV                       200809
POSIX2_C_VERSION                   200809
POSIX2_EXPR_NEST_MAX               32
POSIX2_FORT_DEV                    
POSIX2_FORT_RUN                    
_POSIX2_LINE_MAX                   2048
POSIX2_LINE_MAX                    2048
POSIX2_LOCALEDEF                   200809
POSIX2_RE_DUP_MAX                  32767
POSIX2_SW_DEV                      200809
POSIX2_UPE                         
POSIX2_VERSION                     200809
RE_DUP_MAX                         32767
PATH                               /bin:/usr/bin
CS_PATH                            /bin:/usr/bin
LFS_CFLAGS                         -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
LFS_LDFLAGS                        
LFS_LIBS                           
LFS_LINTFLAGS                      -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
LFS64_CFLAGS                       -D_LARGEFILE64_SOURCE
LFS64_LDFLAGS                      
LFS64_LIBS                         
LFS64_LINTFLAGS                    -D_LARGEFILE64_SOURCE
_XBS5_WIDTH_RESTRICTED_ENVS        XBS5_ILP32_OFF32
XBS5_ILP32_OFFBIG
XBS5_WIDTH_RESTRICTED_ENVS         XBS5_ILP32_OFF32
XBS5_ILP32_OFFBIG
_XBS5_ILP32_OFF32                  1
XBS5_ILP32_OFF32_CFLAGS            
XBS5_ILP32_OFF32_LDFLAGS           
XBS5_ILP32_OFF32_LIBS              
XBS5_ILP32_OFF32_LINTFLAGS         
_XBS5_ILP32_OFFBIG                 1
XBS5_ILP32_OFFBIG_CFLAGS           -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
XBS5_ILP32_OFFBIG_LDFLAGS          
XBS5_ILP32_OFFBIG_LIBS             
XBS5_ILP32_OFFBIG_LINTFLAGS        
_XBS5_LP64_OFF64                   
XBS5_LP64_OFF64_CFLAGS             
XBS5_LP64_OFF64_LDFLAGS            
XBS5_LP64_OFF64_LIBS               
XBS5_LP64_OFF64_LINTFLAGS          
_XBS5_LPBIG_OFFBIG                 
XBS5_LPBIG_OFFBIG_CFLAGS           
XBS5_LPBIG_OFFBIG_LDFLAGS          
XBS5_LPBIG_OFFBIG_LIBS             
XBS5_LPBIG_OFFBIG_LINTFLAGS        
_POSIX_V6_ILP32_OFF32              1
POSIX_V6_ILP32_OFF32_CFLAGS        
POSIX_V6_ILP32_OFF32_LDFLAGS       
POSIX_V6_ILP32_OFF32_LIBS          
POSIX_V6_ILP32_OFF32_LINTFLAGS     
_POSIX_V6_WIDTH_RESTRICTED_ENVS    POSIX_V6_ILP32_OFF32
POSIX_V6_ILP32_OFFBIG
POSIX_V6_WIDTH_RESTRICTED_ENVS     POSIX_V6_ILP32_OFF32
POSIX_V6_ILP32_OFFBIG
_POSIX_V6_ILP32_OFFBIG             1
POSIX_V6_ILP32_OFFBIG_CFLAGS       -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
POSIX_V6_ILP32_OFFBIG_LDFLAGS      
POSIX_V6_ILP32_OFFBIG_LIBS         
POSIX_V6_ILP32_OFFBIG_LINTFLAGS    
_POSIX_V6_LP64_OFF64               
POSIX_V6_LP64_OFF64_CFLAGS         
POSIX_V6_LP64_OFF64_LDFLAGS        
POSIX_V6_LP64_OFF64_LIBS           
POSIX_V6_LP64_OFF64_LINTFLAGS      
_POSIX_V6_LPBIG_OFFBIG             
POSIX_V6_LPBIG_OFFBIG_CFLAGS       
POSIX_V6_LPBIG_OFFBIG_LDFLAGS      
POSIX_V6_LPBIG_OFFBIG_LIBS         
POSIX_V6_LPBIG_OFFBIG_LINTFLAGS    
_POSIX_V7_ILP32_OFF32              1
POSIX_V7_ILP32_OFF32_CFLAGS        
POSIX_V7_ILP32_OFF32_LDFLAGS       
POSIX_V7_ILP32_OFF32_LIBS          
POSIX_V7_ILP32_OFF32_LINTFLAGS     
_POSIX_V7_WIDTH_RESTRICTED_ENVS    POSIX_V7_ILP32_OFF32
POSIX_V7_ILP32_OFFBIG
POSIX_V7_WIDTH_RESTRICTED_ENVS     POSIX_V7_ILP32_OFF32
POSIX_V7_ILP32_OFFBIG
_POSIX_V7_ILP32_OFFBIG             1
POSIX_V7_ILP32_OFFBIG_CFLAGS       -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
POSIX_V7_ILP32_OFFBIG_LDFLAGS      
POSIX_V7_ILP32_OFFBIG_LIBS         
POSIX_V7_ILP32_OFFBIG_LINTFLAGS    
_POSIX_V7_LP64_OFF64               
POSIX_V7_LP64_OFF64_CFLAGS         
POSIX_V7_LP64_OFF64_LDFLAGS        
POSIX_V7_LP64_OFF64_LIBS           
POSIX_V7_LP64_OFF64_LINTFLAGS      
_POSIX_V7_LPBIG_OFFBIG             
POSIX_V7_LPBIG_OFFBIG_CFLAGS       
POSIX_V7_LPBIG_OFFBIG_LDFLAGS      
POSIX_V7_LPBIG_OFFBIG_LIBS         
POSIX_V7_LPBIG_OFFBIG_LINTFLAGS    
_POSIX_ADVISORY_INFO               200809
_POSIX_BARRIERS                    200809
_POSIX_BASE                        
_POSIX_C_LANG_SUPPORT              
_POSIX_C_LANG_SUPPORT_R            
_POSIX_CLOCK_SELECTION             200809
_POSIX_CPUTIME                     200809
_POSIX_THREAD_CPUTIME              200809
_POSIX_DEVICE_SPECIFIC             
_POSIX_DEVICE_SPECIFIC_R           
_POSIX_FD_MGMT                     
_POSIX_FIFO                        
_POSIX_PIPE                        
_POSIX_FILE_ATTRIBUTES             
_POSIX_FILE_LOCKING                
_POSIX_FILE_SYSTEM                 
_POSIX_MONOTONIC_CLOCK             200809
_POSIX_MULTI_PROCESS               
_POSIX_SINGLE_PROCESS              
_POSIX_NETWORKING                  
_POSIX_READER_WRITER_LOCKS         200809
_POSIX_SPIN_LOCKS                  200809
_POSIX_REGEXP                      1
_REGEX_VERSION                     
_POSIX_SHELL                       1
_POSIX_SIGNALS                     
_POSIX_SPAWN                       200809
_POSIX_SPORADIC_SERVER             
_POSIX_THREAD_SPORADIC_SERVER      
_POSIX_SYSTEM_DATABASE             
_POSIX_SYSTEM_DATABASE_R           
_POSIX_TIMEOUTS                    200809
_POSIX_TYPED_MEMORY_OBJECTS        
_POSIX_USER_GROUPS                 
_POSIX_USER_GROUPS_R               
POSIX2_PBS                         
POSIX2_PBS_ACCOUNTING              
POSIX2_PBS_LOCATE                  
POSIX2_PBS_TRACK                   
POSIX2_PBS_MESSAGE                 
SYMLOOP_MAX                        
STREAM_MAX                         16
AIO_LISTIO_MAX                     
AIO_MAX                            
AIO_PRIO_DELTA_MAX                 20
DELAYTIMER_MAX                     2147483647
HOST_NAME_MAX                      64
LOGIN_NAME_MAX                     256
MQ_OPEN_MAX                        
MQ_PRIO_MAX                        32768
_POSIX_DEVICE_IO                   
_POSIX_TRACE                       
_POSIX_TRACE_EVENT_FILTER          
_POSIX_TRACE_INHERIT               
_POSIX_TRACE_LOG                   
RTSIG_MAX                          32
SEM_NSEMS_MAX                      
SEM_VALUE_MAX                      2147483647
SIGQUEUE_MAX                       29184
FILESIZEBITS                       64
POSIX_ALLOC_SIZE_MIN               4096
POSIX_REC_INCR_XFER_SIZE           
POSIX_REC_MAX_XFER_SIZE            
POSIX_REC_MIN_XFER_SIZE            4096
POSIX_REC_XFER_ALIGN               4096
SYMLINK_MAX                        
GNU_LIBC_VERSION                   glibc 2.28
GNU_LIBPTHREAD_VERSION             NPTL 2.28
POSIX2_SYMLINKS                    1
LEVEL1_ICACHE_SIZE                 0
LEVEL1_ICACHE_ASSOC                0
LEVEL1_ICACHE_LINESIZE             0
LEVEL1_DCACHE_SIZE                 0
LEVEL1_DCACHE_ASSOC                0
LEVEL1_DCACHE_LINESIZE             0
LEVEL2_CACHE_SIZE                  0
LEVEL2_CACHE_ASSOC                 0
LEVEL2_CACHE_LINESIZE              0
LEVEL3_CACHE_SIZE                  0
LEVEL3_CACHE_ASSOC                 0
LEVEL3_CACHE_LINESIZE              0
LEVEL4_CACHE_SIZE                  0
LEVEL4_CACHE_ASSOC                 0
LEVEL4_CACHE_LINESIZE              0
IPV6                               200809
RAW_SOCKETS                        200809
_POSIX_IPV6                        200809
_POSIX_RAW_SOCKETS                 200809

Additionally (noting that I'm on a Pi 4B 4GB for this)...

$ cat /proc/meminfo
MemTotal:        3999784 kB
MemFree:         3777568 kB
MemAvailable:    3775124 kB
Buffers:           17508 kB
Cached:            93272 kB
SwapCached:            0 kB
Active:            90948 kB
Inactive:          34104 kB
Active(anon):      14556 kB
Inactive(anon):     8336 kB
Active(file):      76392 kB
Inactive(file):    25768 kB
Unevictable:          16 kB
Mlocked:              16 kB
HighTotal:       3264512 kB
HighFree:        3147080 kB
LowTotal:         735272 kB
LowFree:          630488 kB
SwapTotal:        102396 kB
SwapFree:         102396 kB
Dirty:                 8 kB
Writeback:             0 kB
AnonPages:         14292 kB
Mapped:            21136 kB
Shmem:              8616 kB
Slab:              39964 kB
SReclaimable:      17696 kB
SUnreclaim:        22268 kB
KernelStack:         984 kB
PageTables:          988 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2102288 kB
Committed_AS:     100388 kB
VmallocTotal:     245760 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
Percpu:              608 kB
CmaTotal:         262144 kB
CmaFree:          222976 kB

Correct, much shorter code Ld A, 91; etc
Faster running code

OMG I'm now at the part where I'm controlling GPIO pins with assembly. booya!

1 Like