├── .gitattributes ├── 9781484252864.jpg ├── Contributing.md ├── LICENSE.txt ├── README.md └── Source Code ├── Chapter 1 ├── HelloWorld.s ├── build ├── l.txt └── objdump.txt ├── Chapter 10 ├── debug.s ├── divexamp.s ├── makefile ├── matrixmult.s ├── matrixmult2.s └── mulexamp.s ├── Chapter 11 ├── codesnippets.s ├── debug.s ├── distance.s ├── fpcomp.s ├── main.s ├── maincomp.s └── makefile ├── Chapter 12 ├── debug.s ├── distance.s ├── main.s ├── makefile └── matrixmultneon.s ├── Chapter 13 ├── main.s ├── makefile ├── upper.s ├── upper2.s ├── upper3.s └── upper4.s ├── Chapter 14 ├── div.c ├── makefile ├── od.txt ├── od2.txt ├── upper.c ├── upper.s └── upper2.c ├── Chapter 15 ├── codesnippets.s ├── main.s ├── makefile ├── od2.txt ├── od3.txt ├── odcs.txt ├── upper2.s └── upper3.s ├── Chapter 16 ├── main.s ├── makefile ├── upper.s ├── upper2.s ├── upper3.s └── upper4.s ├── Chapter 2 ├── addexamp1.s ├── addexamp2.s ├── addexamps.s ├── build ├── buildadd ├── buildadd1 ├── buildadd2 ├── codesnippets.s ├── makefile ├── movexamps.s ├── objd.txt └── objdump.txt ├── Chapter 4 ├── codesnippets.s ├── makefile └── printword.s ├── Chapter 5 ├── codesnippets.s ├── makefile ├── od.txt └── upper.s ├── Chapter 6 ├── codesnippets.s ├── gdb.txt ├── main.s ├── mainmacro.s ├── makefile ├── ob.txt ├── obj.txt ├── upper.s └── uppermacro.s ├── Chapter 7 ├── codesnippets.s ├── errno.s ├── fileio.s ├── main.s ├── makefile ├── unistd.s └── upper.s ├── Chapter 8 ├── fileio.s ├── gpiomacros.s ├── gpiomem.s ├── main.s ├── mainmem.s ├── makefile └── unistd.s └── Chapter 9 ├── addexamp2.s ├── debug.s ├── makefile ├── upper.s ├── uppertst.c ├── uppertst4.c └── uppertst5.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /9781484252864.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/Raspberry-Pi-Assembly-Language-Programming/9c5b807db9ad6f865506dd97777f9c732d2eae86/9781484252864.jpg -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Freeware License, some rights reserved 2 | 3 | Copyright (c) 2019 Stephen Smith 4 | 5 | Permission is hereby granted, free of charge, to anyone obtaining a copy 6 | of this software and associated documentation files (the "Software"), 7 | to work with the Software within the limits of freeware distribution and fair use. 8 | This includes the rights to use, copy, and modify the Software for personal use. 9 | Users are also allowed and encouraged to submit corrections and modifications 10 | to the Software for the benefit of other users. 11 | 12 | It is not allowed to reuse, modify, or redistribute the Software for 13 | commercial use in any way, or for a user’s educational materials such as books 14 | or blog articles without prior permission from the copyright holder. 15 | 16 | The above copyright notice and this permission notice need to be included 17 | in all copies or substantial portions of the software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Raspberry Pi Assembly Language Programming: ARM Processor Coding*](https://www.apress.com/9781484252864) by Stephen Smith (Apress, 2019). 4 | 5 | [comment]: #cover 6 | ![Cover image](9781484252864.jpg) 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. -------------------------------------------------------------------------------- /Source Code/Chapter 1/HelloWorld.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to print "Hello World!" 3 | @ to stdout. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R7 - linux function number 7 | @ 8 | 9 | .global _start @ Provide program starting address to linker 10 | 11 | @ Setup the parameters to print hello world 12 | @ and then call Linux to do it. 13 | _start: mov R0, #1 @ 1 = StdOut 14 | ldr R1, =helloworld @ string to print 15 | mov R2, #13 @ length of our string 16 | mov R7, #4 @ linux write system call 17 | svc 0 @ Call linux to output the string 18 | 19 | @ Setup the parameters to exit the program 20 | @ and then call Linux to do it. 21 | mov R0, #0 @ Use 0 return code 22 | mov R7, #1 @ Service command code 1 terminates this program 23 | svc 0 @ Call linux to terminate the program 24 | 25 | .data 26 | helloworld: .ascii "Hello World!\n" 27 | 28 | -------------------------------------------------------------------------------- /Source Code/Chapter 1/build: -------------------------------------------------------------------------------- 1 | as -o HelloWorld.o HelloWorld.s 2 | ld -o HelloWorld HelloWorld.o 3 | -------------------------------------------------------------------------------- /Source Code/Chapter 1/l.txt: -------------------------------------------------------------------------------- 1 | total 16 2 | -rwxr-xr-x 1 pi pi 62 Jun 6 19:25 build 3 | -rwxr-xr-x 1 pi pi 884 Jun 6 19:25 HelloWorld 4 | -rw-r--r-- 1 pi pi 728 Jun 6 19:25 HelloWorld.o 5 | -rw-r--r-- 1 pi pi 803 Jun 6 19:23 HelloWorld.s 6 | -rw-r--r-- 1 pi pi 0 Jun 6 19:34 l.txt 7 | -------------------------------------------------------------------------------- /Source Code/Chapter 1/objdump.txt: -------------------------------------------------------------------------------- 1 | 2 | HelloWorld.o: file format elf32-littlearm 3 | 4 | Contents of section .text: 5 | 0000 0100a0e3 14109fe5 0d20a0e3 0470a0e3 ......... ...p.. 6 | 0010 000000ef 0000a0e3 0170a0e3 000000ef .........p...... 7 | 0020 00000000 .... 8 | Contents of section .data: 9 | 0000 48656c6c 6f20576f 726c6421 0a Hello World!. 10 | Contents of section .ARM.attributes: 11 | 0000 41130000 00616561 62690001 09000000 A....aeabi...... 12 | 0010 06010801 .... 13 | 14 | Disassembly of section .text: 15 | 16 | 00000000 <_start>: 17 | 0: e3a00001 mov r0, #1 18 | 4: e59f1014 ldr r1, [pc, #20] ; 20 <_start+0x20> 19 | 8: e3a0200d mov r2, #13 20 | c: e3a07004 mov r7, #4 21 | 10: ef000000 svc 0x00000000 22 | 14: e3a00000 mov r0, #0 23 | 18: e3a07001 mov r7, #1 24 | 1c: ef000000 svc 0x00000000 25 | 20: 00000000 .word 0x00000000 26 | -------------------------------------------------------------------------------- /Source Code/Chapter 10/debug.s: -------------------------------------------------------------------------------- 1 | @ Various macros to help with debugging 2 | 3 | @ These macros preseve all registers. 4 | @ Beware they will change cpsr. 5 | 6 | .macro printReg reg 7 | push {r0-r4, lr} @ save regs 8 | mov r2, R\reg @ for the %d 9 | mov r3, R\reg @ for the %x 10 | mov r1, #\reg 11 | add r1, #'0' @ for %c 12 | ldr r0, =ptfStr @ printf format str 13 | bl printf @ call printf 14 | pop {r0-r4, lr} @ restore regs 15 | .endm 16 | 17 | .macro printStr str 18 | push {r0-r4, lr} @ save regs 19 | ldr r0, =1f @ load print str 20 | bl printf @ call printf 21 | pop {r0-r4, lr} @ restore regs 22 | b 2f @ branch around str 23 | 1: .asciz "\str\n" 24 | .align 4 25 | 2: 26 | .endm 27 | 28 | .data 29 | ptfStr: .asciz "R%c = %16d, 0x%08x\n" 30 | .align 4 31 | .text 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 10/divexamp.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Examples of 32-Bit Integer Division 3 | @ 4 | 5 | .include "debug.s" 6 | 7 | .global main @ Provide program starting address to linker 8 | 9 | @ Load the registers with some data 10 | @ Perform various division instructions 11 | main: 12 | push {R4-R12, LR} 13 | MOV R2, #100 14 | MOV R3, #4 15 | 16 | printStr "Inputs:" 17 | printReg 2 18 | printReg 3 19 | 20 | SDIV R4, R2, R3 21 | printStr "Outputs:" 22 | printReg 4 23 | 24 | UDIV R4, R2, R3 25 | printStr "Outputs:" 26 | printReg 4 27 | 28 | mov r0, #0 @ return code 29 | pop {R4-R12, PC} 30 | 31 | -------------------------------------------------------------------------------- /Source Code/Chapter 10/makefile: -------------------------------------------------------------------------------- 1 | 2 | ifdef DEBUG 3 | DEBUGFLGS = -g 4 | else 5 | DEBUGFLGS = 6 | endif 7 | LSTFLGS = 8 | 9 | all: divexamp mulexamp matrixmult matrixmult2 10 | 11 | %.o : %.s 12 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 13 | 14 | divexamp: divexamp.s debug.s 15 | gcc -march="armv8-a" -o divexamp divexamp.s 16 | 17 | mulexamp: mulexamp.s debug.s 18 | gcc -o mulexamp mulexamp.s 19 | 20 | matrixmult: matrixmult.s 21 | gcc -g -o matrixmult matrixmult.s 22 | 23 | matrixmult2: matrixmult2.s 24 | gcc -g -o matrixmult2 matrixmult2.s 25 | 26 | -------------------------------------------------------------------------------- /Source Code/Chapter 10/matrixmult.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Multiply 2 3x3 integer matrices 4 | @ 5 | @ Registers: 6 | @ R1 - Row index 7 | @ R2 - Column index 8 | @ R4 - Address of row 9 | @ R5 - Address of column 10 | @ R7 - 64 bit accumulated sum 11 | @ R8 - 64 bit accumulated sum 12 | @ R9 - Cell of A 13 | @ R10 - Cell of B 14 | @ R11 - Position in C 15 | @ R12 - row in dotloop 16 | @ R6 - col in dotloop 17 | 18 | .global main @ Provide program starting address to linker 19 | 20 | .equ N, 3 @ Matrix dimensions 21 | .equ WDSIZE, 4 @ Size of element 22 | main: 23 | push {R4-R12, LR} @ Save required regs 24 | 25 | MOV R1, #N @ Row index 26 | LDR R4, =A @ Address of current row 27 | LDR R11, =C @ Address of results matrix 28 | rowloop: 29 | LDR R5, =B @ first column in B 30 | MOV R2, #N @ Column index (will count down to 0) 31 | 32 | colloop: 33 | @ Zero accumulator registers 34 | MOV R7, #0 35 | MOV R8, #0 36 | 37 | MOV R0, #N @ dot product loop counter 38 | MOV R12, R4 @ row for dot product 39 | MOV R6, R5 @ column for dot product 40 | dotloop: 41 | @ Do dot product of a row of A with column of B 42 | LDR R9, [R12], #WDSIZE @ load A[row, i] and incr 43 | LDR R10, [R6], #(N*WDSIZE) @ load B[i, col] 44 | SMLAL R7, R8, R9, R10 @ Do multiply and accumulate 45 | SUBS R0, #1 @ Dec loop counter 46 | BNE dotloop @ If not zero loop 47 | 48 | STR R7, [R11], #4 @ C[row, col] = dotprod 49 | ADD R5, #WDSIZE @ Increment current col 50 | SUBS R2, #1 @ Dec col loop counter 51 | BNE colloop @ If not zero loop 52 | 53 | ADD R4, #(N*WDSIZE) @ Increment to next row 54 | SUBS R1, #1 @ Dec row loop counter 55 | BNE rowloop @ If not zero loop 56 | 57 | @ Print out matrix C 58 | @ Loop through 3 rows printing 3 cols each time. 59 | MOV R5, #3 @ Print 3 rows 60 | LDR R11, =C @ Addr of results matrix 61 | printloop: 62 | 63 | LDR R0, =prtstr @ printf format string 64 | LDR R1, [R11], #WDSIZE @ first element in current row 65 | LDR R2, [R11], #WDSIZE @ second element in current row 66 | LDR R3, [R11], #WDSIZE @ third element in curent row 67 | BL printf @ Call printf 68 | SUBS R5, #1 @ Dec loop counter 69 | BNE printloop @ If not zero loop 70 | 71 | mov r0, #0 @ return code 72 | pop {R4-R12, PC} @ Restore regs and return 73 | 74 | .data 75 | @ First matrix 76 | A: .word 1, 2, 3 77 | .word 4, 5, 6 78 | .word 7, 8, 9 79 | @ Second matrix 80 | B: .word 9, 8, 7 81 | .word 6, 5, 4 82 | .word 3, 2, 1 83 | @ Result matix 84 | C: .fill 9, 4, 0 85 | 86 | prtstr: .asciz "%3d %3d %3d\n" 87 | -------------------------------------------------------------------------------- /Source Code/Chapter 10/matrixmult2.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Multiply 2 3x3 integer matrices 4 | @ Uses a dual multiply/accumulate instruction 5 | @ so processes two elements in the dot product 6 | @ per loop. 7 | @ 8 | @ Registers: 9 | @ R1 - Row index 10 | @ R2 - Column index 11 | @ R4 - Address of row 12 | @ R5 - Address of column 13 | @ R7 - 64 bit accumulated sum 14 | @ R8 - 64 bit accumulated sum 15 | @ R9 - Cell of A 16 | @ R10 - Cell of B 17 | @ R11 - Position in C 18 | @ R12 - row in dotloop 19 | @ R6 - col in dotloop 20 | 21 | .global main @ Provide program starting address to linker 22 | 23 | .equ N, 3 @ Matrix dimensions 24 | .equ ELSIZE, 2 @ Size of element 25 | main: 26 | push {R4-R12, LR} @ Save required regs 27 | 28 | MOV R1, #N @ Row index 29 | LDR R4, =A @ Address of current row 30 | LDR R11, =C @ Address of results matrix 31 | rowloop: 32 | LDR R5, =B @ first column in B 33 | MOV R2, #N @ Column index (will count down to 0) 34 | 35 | colloop: 36 | @ Zero accumulator registers 37 | MOV R7, #0 38 | MOV R8, #0 39 | 40 | MOV R0, #((N+1)/2) @ dot product loop counter 41 | MOV R12, R4 @ row for dot product 42 | MOV R6, R5 @ column for dot product 43 | dotloop: 44 | @ Do dot product of a row of A with column of B 45 | LDR R9, [R12], #(ELSIZE*2) @ load A[row, i] and incr 46 | LDR R10, [R6], #(ELSIZE*2) @ load B[i, col] 47 | SMLAD R7, R9, R10, R7 @ Do dual multiply and accumulate 48 | SUBS R0, #1 @ Dec loop counter 49 | BNE dotloop @ If not zero loop 50 | 51 | STR R7, [R11], #4 @ C[row, col] = dotprod 52 | ADD R5, #((N+1)*ELSIZE) @ Increment current col 53 | SUBS R2, #1 @ Dec col loop counter 54 | BNE colloop @ If not zero loop 55 | 56 | ADD R4, #((N+1)*ELSIZE) @ Increment to next row 57 | SUBS R1, #1 @ Dec row loop counter 58 | BNE rowloop @ If not zero loop 59 | 60 | @ Print out matrix C 61 | @ Loop through 3 rows printing 3 cols each time. 62 | MOV R5, #3 @ Print 3 rows 63 | LDR R11, =C @ Addr of results matrix 64 | printloop: 65 | 66 | LDR R0, =prtstr @ printf format string 67 | LDR R1, [R11], #4 @ first element in current row 68 | LDR R2, [R11], #4 @ second element in current row 69 | LDR R3, [R11], #4 @ third element in curent row 70 | BL printf @ Call printf 71 | SUBS R5, #1 @ Dec loop counter 72 | BNE printloop @ If not zero loop 73 | 74 | mov r0, #0 @ return code 75 | pop {R4-R12, PC} @ Restore regs and return 76 | 77 | .data 78 | @ First matrix 79 | A: .short 1, 2, 3, 0 80 | .short 4, 5, 6, 0 81 | .short 7, 8, 9, 0 82 | @ Second matrix 83 | B: .short 9, 6, 3, 0 84 | .short 8, 5, 2, 0 85 | .short 7, 4, 1, 0 86 | @ Result matix 87 | C: .fill 9, 4, 0 88 | 89 | prtstr: .asciz "%3d %3d %3d\n" 90 | -------------------------------------------------------------------------------- /Source Code/Chapter 10/mulexamp.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Example of 16 & 32-Bit Multiplication 4 | @ 5 | 6 | .include "debug.s" 7 | 8 | .global main @ Provide program starting address to linker 9 | 10 | @ Load the registers with some data 11 | @ Use small positive numbers that will work for all 12 | @ multiply instructions. 13 | main: 14 | push {R4-R12, LR} 15 | MOV R2, #25 16 | MOV R3, #4 17 | 18 | 19 | printStr "Inputs:" 20 | printReg 2 21 | printReg 3 22 | 23 | MUL R4, R2, R3 24 | printStr "MUL R4=R2*R3:" 25 | printReg 4 26 | 27 | SMULL R4, R5, R2, R3 28 | printStr "SMULL R5, R4=R2*R3:" 29 | printReg 4 30 | printReg 5 31 | 32 | UMULL R4, R5, R2, R3 33 | printStr "UMULL R5, R4=R2*R3:" 34 | printReg 4 35 | printReg 5 36 | 37 | SMMUL R4, R2, R3 38 | printStr "SMMUL R4 = top 32 bits of R2*R3:" 39 | printReg 4 40 | 41 | SMULBB R4, R2, R3 42 | printStr "SMULBB R4 = R2*R3:" 43 | printReg 4 44 | 45 | SMULWB R4, R2, R3 46 | printStr "SMULWB R4 = upper 32 bits of R2*R3:" 47 | printReg 4 48 | 49 | mov r0, #0 @ return code 50 | pop {R4-R12, PC} 51 | 52 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 11. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .global _start 10 | 11 | _start: 12 | l1: VPUSH {S16-S31} 13 | VPOP {S16-S31} 14 | 15 | l2: LDR R1, =fp1 16 | VLDR S4, [R1] 17 | VLDR S4, [R1, #4] 18 | VSTR S4, [R1] 19 | VSTR S4, [R1, #4] 20 | 21 | l3: VADD.F32 S4, S1 22 | 23 | l4: VMRS APSR_nzcv, FPSCR 24 | 25 | @ Setup the parameters to exit the program 26 | @ and then call Linux to do it. 27 | MOV R0, #0 @ Use 0 return code 28 | MOV R7, #1 @ Service command code 1 terminates this program 29 | SVC 0 @ Call linux to terminate the program 30 | 31 | .data 32 | .single 1.343, 4.343e20, -0.4343, -0.4444e-10 33 | .double -4.24322322332e-10, 3.141592653589793 34 | fp1: .single 3.14159 35 | fp2: .single 4.3341 36 | fp3: .single 0.0 37 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/debug.s: -------------------------------------------------------------------------------- 1 | @ Various macros to help with debugging 2 | 3 | @ These macros preseve all registers. 4 | @ Beware they will change cpsr. 5 | 6 | .macro printReg reg 7 | push {r0-r4, lr} @ save regs 8 | mov r2, R\reg @ for the %d 9 | mov r3, R\reg @ for the %x 10 | mov r1, #\reg 11 | add r1, #'0' @ for %c 12 | ldr r0, =ptfStr @ printf format str 13 | bl printf @ call printf 14 | pop {r0-r4, lr} @ restore regs 15 | .endm 16 | 17 | .macro printStr str 18 | push {r0-r4, lr} @ save regs 19 | ldr r0, =1f @ load print str 20 | bl printf @ call printf 21 | pop {r0-r4, lr} @ restore regs 22 | b 2f @ branch around str 23 | 1: .asciz "\str\n" 24 | .align 4 25 | 2: 26 | .endm 27 | 28 | .data 29 | ptfStr: .asciz "R%c = %16d, 0x%08x\n" 30 | .align 4 31 | .text 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/distance.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Example function to calculate the distance 4 | @ between two points in single precision 5 | @ floating point. 6 | @ 7 | @ Inputs: 8 | @ R0 - pointer to the 4 FP numbers 9 | @ they are x1, y1, x2, y2 10 | @ Outputs: 11 | @ R0 - the length (as single precision FP) 12 | 13 | .global distance @ Allow function to be called by others 14 | 15 | @ 16 | distance: 17 | @ push all registers to be safe, we don't really 18 | @ need to push so many. 19 | push {R4-R12, LR} 20 | vpush {S16-S31} 21 | 22 | @ load all 4 numbers at once 23 | vldm R0, {S0-S3} 24 | 25 | @ calc s4 = x2 - x1 26 | vsub.f32 S4, S2, S0 27 | @ calc s5 = y2 - y1 28 | vsub.f32 S5, S3, S1 29 | @ calc s4 = S4 * S4 (x2-X1)^2 30 | vmul.f32 S4, S4 31 | @ calc s5 = s5 * s5 (Y2-Y1)^2 32 | vmul.f32 S5, S5 33 | @ calc S4 = S4 + S5 34 | vadd.f32 S4, S5 35 | @ calc sqrt(S4) 36 | vsqrt.f32 S4, S4 37 | @ move result to R0 to be returned 38 | vmov R0, S4 39 | 40 | @ restore what we preserved. 41 | vpop {S16-S31} 42 | pop {R4-R12, PC} 43 | 44 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/fpcomp.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Function to compare to floating point numbers 4 | @ the parameters are a pointer to the two numbers 5 | @ and an error epsilon. 6 | @ 7 | @ Inputs: 8 | @ R0 - pointer to the 3 FP numbers 9 | @ they are x1, x2, e 10 | @ Outputs: 11 | @ R0 - 1 if they are equal, else 0 12 | 13 | .global fpcomp @ Allow function to be called by others 14 | 15 | @ 16 | fpcomp: 17 | @ push all registers to be safe, we don't really 18 | @ need to push so many. 19 | push {R4-R12, LR} 20 | vpush {S16-S31} 21 | 22 | @ load all 3 numbers at once 23 | vldm R0, {S0-S2} 24 | 25 | @ calc s3 = x2 - x1 26 | vsub.f32 S3, S1, S0 27 | vabs.f32 S3, S3 28 | vcmp.f32 S3, S2 29 | vmrs APSR_nzcv, FPSCR 30 | BLE notequal 31 | MOV R0, #1 32 | B done 33 | 34 | notequal:MOV R0, #0 35 | 36 | @ restore what we preserved. 37 | done: vpop {S16-S31} 38 | pop {R4-R12, PC} 39 | 40 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/main.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Main program to test our distance function 4 | @ 5 | @ r7 - loop counter 6 | @ r8 - address to current set of points 7 | 8 | .global main @ Provide program starting address to linker 9 | 10 | @ 11 | 12 | .equ N, 3 @ Number of points. 13 | 14 | main: 15 | push {R4-R12, LR} 16 | 17 | ldr r8, =points @ pointer to current points 18 | 19 | mov r7, #N @ number of loop iterations 20 | 21 | loop: mov r0, r8 @ move pointer to parameter 1 (r0) 22 | 23 | bl distance @ call distance function 24 | 25 | @ need to take the single precision return value 26 | @ and convert it to a double, because the C printf 27 | @ function can only print doubles. 28 | vmov s2, r0 @ move back to fpu for conversion 29 | vcvt.f64.f32 d0, s2 @ convert single to double 30 | vmov r2, r3, d0 @ return double to r2, r3 31 | ldr r0, =prtstr @ load print string 32 | bl printf @ print the distance 33 | 34 | add r8, #(4*4) @ 4 points each 4 bytes 35 | subs r7, #1 @ decrement loop counter 36 | bne loop @ loop if more points 37 | 38 | mov r0, #0 @ return code 39 | pop {R4-R12, PC} 40 | 41 | .data 42 | points: .single 0.0, 0.0, 3.0, 4.0 43 | .single 1.3, 5.4, 3.1, -1.5 44 | .single 1.323e10, -1.2e-4, 34.55, 5454.234 45 | prtstr: .asciz "Distance = %f\n" 46 | 47 | 48 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/maincomp.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Main program to test our distance function 4 | @ 5 | @ r7 - loop counter 6 | @ r8 - address to current set of points 7 | 8 | .global main @ Provide program starting address to linker 9 | 10 | @ 11 | 12 | .equ N, 100 @ Number of additions. 13 | 14 | main: 15 | push {R4-R12, LR} 16 | 17 | @ Add up one hundred cents and test if they equal $1.00 18 | 19 | mov r7, #N @ number of loop iterations 20 | 21 | @ load cents, running sum and real sum to FPU 22 | ldr r0, =cent 23 | vldm r0, {S0-S2} 24 | loop: 25 | @ add cent to running sum 26 | vadd.f32 s1, s0 27 | subs r7, #1 @ decrement loop counter 28 | bne loop @ loop if more points 29 | 30 | @ compare running sum to real sum 31 | vcmp.f32 s1, s2 32 | @ copy FPSCR to CSPR 33 | vmrs APSR_nzcv, FPSCR 34 | @ print if the numbers are equal or not 35 | beq equal 36 | ldr r0, =notequalstr 37 | bl printf 38 | b next 39 | equal: ldr r0, =equalstr 40 | bl printf 41 | 42 | next: 43 | @ load pointer to running sum, real sum and epsilon 44 | ldr r0, =runsum 45 | vldm r0, {S0-S2} 46 | @ call comparison function 47 | bl fpcomp @ call comparison function 48 | @ compare return code to 1 and print if the numbers 49 | @ are equal or not (within epsilon). 50 | cmp r0, #1 51 | beq equal2 52 | ldr r0, =notequalstr 53 | bl printf 54 | b done 55 | equal2: ldr r0, =equalstr 56 | bl printf 57 | 58 | done: mov r0, #0 @ return code 59 | pop {R4-R12, PC} 60 | 61 | .data 62 | cent: .single 0.01 63 | runsum: .single 0.0 64 | sum: .single 1.00 65 | epsilon:.single 0.00001 66 | equalstr: .asciz "equal\n" 67 | notequalstr: .asciz "not equal\n" 68 | 69 | 70 | -------------------------------------------------------------------------------- /Source Code/Chapter 11/makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | ifdef DEBUG 4 | DEBUGFLGS = -g 5 | else 6 | DEBUGFLGS = 7 | endif 8 | LSTFLGS = 9 | 10 | all: codesnippets distance fpcomp 11 | 12 | %.o : %.s 13 | as -mfpu=vfp $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 14 | 15 | codesnippets: codesnippets.o 16 | ld -o codesnippets codesnippets.o 17 | 18 | distance: distance.s main.s 19 | gcc -g -o distance distance.s main.s 20 | 21 | fpcomp: fpcomp.s maincomp.s 22 | gcc -g -o fpcomp fpcomp.s maincomp.s 23 | -------------------------------------------------------------------------------- /Source Code/Chapter 12/debug.s: -------------------------------------------------------------------------------- 1 | @ Various macros to help with debugging 2 | 3 | @ These macros preseve all registers. 4 | @ Beware they will change cpsr. 5 | 6 | .macro printReg reg 7 | push {r0-r4, lr} @ save regs 8 | mov r2, R\reg @ for the %d 9 | mov r3, R\reg @ for the %x 10 | mov r1, #\reg 11 | add r1, #'0' @ for %c 12 | ldr r0, =ptfStr @ printf format str 13 | bl printf @ call printf 14 | pop {r0-r4, lr} @ restore regs 15 | .endm 16 | 17 | .macro printStr str 18 | push {r0-r4, lr} @ save regs 19 | ldr r0, =1f @ load print str 20 | bl printf @ call printf 21 | pop {r0-r4, lr} @ restore regs 22 | b 2f @ branch around str 23 | 1: .asciz "\str\n" 24 | .align 4 25 | 2: 26 | .endm 27 | 28 | .data 29 | ptfStr: .asciz "R%c = %16d, 0x%08x\n" 30 | .align 4 31 | .text 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 12/distance.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Example function to calculate the distance 4 | @ between 4D two points in single precision 5 | @ floating point using the NEON Processor 6 | @ 7 | @ Inputs: 8 | @ R0 - pointer to the 8 FP numbers 9 | @ they are (x1, x2, x3, x4), 10 | @ (y1, y2, y3, y4) 11 | @ Outputs: 12 | @ R0 - the length (as single precision FP) 13 | 14 | .global distance @ Allow function to be called by others 15 | 16 | @ 17 | distance: 18 | @ push all registers to be safe, we don't really 19 | @ need to push so many. 20 | push {R4-R12, LR} 21 | vpush {S16-S31} 22 | 23 | @ load all 4 numbers at once 24 | vldm R0, {Q2-Q3} 25 | 26 | @ calc q1 = q2 - q3 27 | vsub.f32 Q1, Q2, Q3 28 | @ calc Q1 = Q1 * Q1 (xi-yi)^2 29 | vmul.f32 Q1, Q1, Q1 30 | @ calc S0 = S0 + S1 + S2 + S3 31 | vpadd.f32 D0, D2, D3 32 | vadd.f32 S0, S1 33 | @ calc sqrt(S4) 34 | vsqrt.f32 S4, S0 35 | @ move result to R0 to be returned 36 | vmov R0, S4 37 | 38 | @ restore what we preserved. 39 | vpop {S16-S31} 40 | pop {R4-R12, PC} 41 | 42 | -------------------------------------------------------------------------------- /Source Code/Chapter 12/main.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Main program to test our distance function 4 | @ 5 | @ r7 - loop counter 6 | @ r8 - address to current set of points 7 | 8 | .global main @ Provide program starting address to linker 9 | 10 | @ 11 | 12 | .equ N, 3 @ Number of points. 13 | 14 | main: 15 | push {R4-R12, LR} 16 | 17 | ldr r8, =points @ pointer to current points 18 | 19 | mov r7, #N @ number of loop iterations 20 | 21 | loop: mov r0, r8 @ move pointer to parameter 1 (r0) 22 | 23 | bl distance @ call distance function 24 | 25 | @ need to take the single precision return value 26 | @ and convert it to a double, because the C printf 27 | @ function can only print doubles. 28 | vmov s2, r0 @ move back to fpu for conversion 29 | vcvt.f64.f32 d0, s2 @ convert single to double 30 | vmov r2, r3, d0 @ return double to r2, r3 31 | ldr r0, =prtstr @ load print string 32 | bl printf @ print the distance 33 | 34 | add r8, #(8*4) @ 8 elements each 4 bytes 35 | subs r7, #1 @ decrement loop counter 36 | bne loop @ loop if more points 37 | 38 | mov r0, #0 @ return code 39 | pop {R4-R12, PC} 40 | 41 | .data 42 | points: .single 0.0, 0.0, 0.0, 0.0, 17.0, 4.0, 2.0, 1.0 43 | .single 1.3, 5.4, 3.1, -1.5, -2.4, 0.323, 3.4, -0.232 44 | .single 1.323e10, -1.2e-4, 34.55, 5454.234, 10.9, -3.6, 4.2, 1.3 45 | prtstr: .asciz "Distance = %f\n" 46 | 47 | 48 | -------------------------------------------------------------------------------- /Source Code/Chapter 12/makefile: -------------------------------------------------------------------------------- 1 | 2 | ifdef DEBUG 3 | DEBUGFLGS = -g 4 | else 5 | DEBUGFLGS = 6 | endif 7 | LSTFLGS = 8 | 9 | all: matrixmultneon distance 10 | 11 | %.o : %.s 12 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 13 | 14 | matrixmultneon: matrixmultneon.s 15 | gcc -mfpu=neon-vfpv4 -g -o matrixmultneon matrixmultneon.s 16 | 17 | distance: distance.s main.s 18 | gcc -mfpu=neon-vfpv4 -g -o distance distance.s main.s 19 | -------------------------------------------------------------------------------- /Source Code/Chapter 12/matrixmultneon.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Multiply 2 3x3 integer matrices 4 | @ Uses the NEON Coprocessor to do 5 | @ some operations in parallel. 6 | @ 7 | @ Registers: 8 | @ D0 - first column of matrix A 9 | @ D1 - second column of matrix A 10 | @ D2 - third column of matrix A 11 | @ D3 - first column of matrix B 12 | @ D4 - second column of matrix B 13 | @ D5 - third column of matrix B 14 | @ D6 - first column of matrix C 15 | @ D7 - second column of matrix C 16 | @ D8 - third column of matrix C 17 | 18 | .global main @ Provide program starting address to linker 19 | 20 | main: 21 | push {R4-R12, LR} @ Save required regs 22 | 23 | @ load matrix A into Neon registers D0, D1, D2 24 | LDR R0, =A @ Address of A 25 | VLDM R0, {D0-D2} @ bulk load the three columns 26 | 27 | @ load matrix B into Neon registers D3, D4, D5 28 | LDR R0, =B @ Address of B 29 | VLDM R0, {D3-D5} @ bulk load the three columns 30 | 31 | .macro mulcol ccol bcol 32 | VMUL.I16 \ccol, D0, \bcol[0] 33 | VMLA.I16 \ccol, D1, \bcol[1] 34 | VMLA.I16 \ccol, D2, \bcol[2] 35 | .endm 36 | 37 | mulcol D6, D3 @ process first column 38 | mulcol D7, D4 @ process second column 39 | mulcol D8, D5 @ process third column 40 | 41 | LDR R1, =C @ Address of C 42 | VSTM R1, {D6-D8} @ buld store the three columns 43 | 44 | @ Print out matrix C 45 | @ Loop through 3 rows printing 3 cols each time. 46 | MOV R5, #3 @ Print 3 rows 47 | LDR R11, =C @ Addr of results matrix 48 | printloop: 49 | 50 | LDR R0, =prtstr @ printf format string 51 | @ print transpose so matrix is in usual row column order. 52 | @ first ldrh post-indexes by 2 for next row 53 | @ so second ldrh adds 6, so is ahead by 2+6=8=row size 54 | @ simlarly for third ldh ahead by 2+14=16 = 2 x row size 55 | LDRH R1, [R11], #2 @ first element in current row 56 | LDRH R2, [R11,#6] @ second element in current row 57 | LDRH R3, [R11,#14] @ third element in curent row 58 | BL printf @ Call printf 59 | SUBS R5, #1 @ Dec loop counter 60 | BNE printloop @ If not zero loop 61 | 62 | mov r0, #0 @ return code 63 | pop {R4-R12, PC} @ Restore regs and return 64 | 65 | .data 66 | @ First matrix in column major order 67 | A: .short 1, 4, 7, 0 68 | .short 2, 5, 8, 0 69 | .short 3, 6, 9, 0 70 | @ Second matrix in column major order 71 | B: .short 9, 6, 3, 0 72 | .short 8, 5, 2, 0 73 | .short 7, 4, 1, 0 74 | @ Result matix in column major order 75 | C: .fill 12, 2, 0 76 | 77 | prtstr: .asciz "%3d %3d %3d\n" 78 | -------------------------------------------------------------------------------- /Source Code/Chapter 13/main.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case by calling a function. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R1 - address of output string 7 | @ R0 - address of input string 8 | @ R5 - current character being processed 9 | @ R7 - linux function number 10 | @ 11 | 12 | .global _start @ Provide program starting address to linker 13 | 14 | _start: LDR R0, =instr @ start of input string 15 | LDR R1, =outstr @ address of output string 16 | MOV R4, #12 17 | MOV R5, #13 18 | 19 | BL toupper 20 | 21 | @ Setup the parameters to print our hex number 22 | @ and then call Linux to do it. 23 | MOV R2,R0 @ return code is the length of the string 24 | 25 | MOV R0, #1 @ 1 = StdOut 26 | LDR R1, =outstr @ string to print 27 | MOV R7, #4 @ linux write system call 28 | SVC 0 @ Call linux to output the string 29 | 30 | @ Setup the parameters to exit the program 31 | @ and then call Linux to do it. 32 | MOV R0, #0 @ Use 0 return code 33 | MOV R7, #1 @ Service command code 1 terminates this program 34 | SVC 0 @ Call linux to terminate the program 35 | 36 | .data 37 | instr: .asciz "This is our Test String that we will convert. AaZz@[`{\n" 38 | .align 4 39 | outstr: .fill 255, 1, 0 40 | 41 | -------------------------------------------------------------------------------- /Source Code/Chapter 13/makefile: -------------------------------------------------------------------------------- 1 | UPPEROBJS = main.o upper.o 2 | UPPER2OBJS = main.o upper2.o 3 | UPPER3OBJS = upper3.o 4 | UPPER4OBJS = main.o upper4.o 5 | 6 | ifdef DEBUG 7 | DEBUGFLGS = -g 8 | else 9 | DEBUGFLGS = 10 | endif 11 | LSTFLGS = 12 | 13 | all: upper upper2 upper3 upper4 14 | 15 | %.o : %.s 16 | as -mfpu=neon-vfpv4 $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 17 | 18 | upper: $(UPPEROBJS) 19 | ld -o upper $(UPPEROBJS) 20 | 21 | upper2: $(UPPER2OBJS) 22 | ld -o upper2 $(UPPER2OBJS) 23 | 24 | upper3: $(UPPER3OBJS) 25 | ld -o upper3 $(UPPER3OBJS) 26 | 27 | upper4: $(UPPER4OBJS) 28 | ld -o upper4 $(UPPER4OBJS) 29 | -------------------------------------------------------------------------------- /Source Code/Chapter 13/upper.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ R6 - minus 'a' to compare < 26. 10 | @ 11 | 12 | .global toupper @ Allow other files to call this routine 13 | 14 | toupper: PUSH {R4-R6} @ Save the registers we use. 15 | MOV R4, R1 16 | @ The loop is until byte pointed to by R1 is non-zero 17 | loop: LDRB R5, [R0], #1 @ load character and increment pointer 18 | @ Want to know if 'a' <= R5 <= 'z' 19 | @ First subtract 'a' 20 | SUB R6, R5, #'a' 21 | @ Now want to know if R6 <= 25 22 | CMP R6, #25 @ chars are 0-25 after shift 23 | BHI cont 24 | @ if we got here then the letter is lowercase, so convert it. 25 | SUB R5, #('a'-'A') 26 | cont: @ end if 27 | STRB R5, [R1], #1 @ store character to output str 28 | CMP R5, #0 @ stop on hitting a null character 29 | BNE loop @ loop if character isn't null 30 | SUB R0, R1, R4 @ get the length by subtracting the pointers 31 | POP {R4-R6} @ Restore the register we use. 32 | BX LR @ Return to caller 33 | -------------------------------------------------------------------------------- /Source Code/Chapter 13/upper2.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ R6 - minus 'a' to compare < 26. 10 | @ 11 | 12 | .global toupper @ Allow other files to call this routine 13 | 14 | toupper: PUSH {R4-R6} @ Save the registers we use. 15 | MOV R4, R1 16 | @ The loop is until byte pointed to by R1 is non-zero 17 | loop: LDRB R5, [R0], #1 @ load character and increment pointer 18 | @ Want to know if 'a' <= R5 <= 'z' 19 | @ First subtract 'a' 20 | SUB R6, R5, #'a' 21 | @ Now want to know if R6 <= 25 22 | CMP R6, #25 @ chars are 0-25 after shift 23 | @ if we got here then the letter is lowercase, so convert it. 24 | SUBLS R5, #('a'-'A') 25 | STRB R5, [R1], #1 @ store character to output str 26 | CMP R5, #0 @ stop on hitting a null character 27 | BNE loop @ loop if character isn't null 28 | SUB R0, R1, R4 @ get the length by subtracting the pointers 29 | POP {R4-R6} @ Restore the register we use. 30 | BX LR @ Return to caller 31 | -------------------------------------------------------------------------------- /Source Code/Chapter 13/upper3.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. Assumes only alphabetic 4 | @ characters. Uses bit clear blindly without 5 | @ checking if character is alphabetic or not. 6 | @ 7 | @ R0 - address of input string 8 | @ R1 - address of output string 9 | @ R2 - original output string for length calc. 10 | @ R3 - current character being processed 11 | @ 12 | 13 | .global _start @ Provide program starting address to linker 14 | 15 | .MACRO toupper inputstr, outputstr 16 | LDR R0, =\inputstr @ start of input string 17 | LDR R1, =\outputstr @ address of output string 18 | MOV R2, R1 19 | @ The loop is until byte pointed to by R1 is non-zero 20 | loop: LDRB R3, [R0], #1 @ load character and increment pointer 21 | BIC R3, #0x20 @ kill the bit that makes it lower case 22 | STRB R3, [R1], #1 @ store character to output str 23 | CMP R3, #0 @ stop on hitting a null charactser 24 | BNE loop @ loop if character isn't null 25 | SUB R0, R1, R2 @ get the length by subtracting the pointers 26 | .ENDM 27 | 28 | _start: 29 | toupper instr, outstr 30 | 31 | @ Setup the parameters to print our hex number 32 | @ and then call Linux to do it. 33 | MOV R2,R0 @ return code is the length of the string 34 | 35 | MOV R0, #1 @ 1 = StdOut 36 | LDR R1, =outstr @ string to print 37 | MOV R7, #4 @ linux write system call 38 | SVC 0 @ Call linux to output the string 39 | 40 | @ Setup the parameters to exit the program 41 | @ and then call Linux to do it. 42 | MOV R0, #0 @ Use 0 return code 43 | MOV R7, #1 @ Service command code 1 terminates this program 44 | SVC 0 @ Call linux to terminate the program 45 | 46 | .data 47 | instr: .asciz "ThisIsRatherALargeVariableNameAaZz@[`{\n" 48 | .align 4 49 | outstr: .fill 255, 1, 0 50 | -------------------------------------------------------------------------------- /Source Code/Chapter 13/upper4.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R0 - address of input string 6 | @ R1 - address of output string 7 | @ Q0 - 8 characters to be processed 8 | @ Q1 - contains all a's for comparison 9 | @ Q2 - result of comparison with 'a's 10 | @ Q3 - all 25's for comp 11 | @ Q8 - spaces for bic operation 12 | 13 | .global toupper @ Allow other files to call this routine 14 | 15 | .EQU N, 4 16 | toupper: 17 | LDR R3, =aaas 18 | VLDM R3, {Q1} @ Load Q1 with all a's 19 | LDR R3, =endch 20 | VLDM R3, {Q3} @ Load Q3 with all 25's 21 | LDR R3, =spaces 22 | VLDM R3, {Q8} @ Load Q8 with all spaces 23 | MOV R3, #N 24 | @ The loop is until byte pointed to by R1 is non-zero 25 | loop: VLDM R0!, {Q0} @ load 16 characters and increment pointer 26 | VSUB.U8 Q2, Q0, Q1 @ Subtract 'a's 27 | VCLE.U8 Q2, Q2, Q3 @ compare chars to 25's 28 | VAND.U8 Q2, Q2,Q8 @ and result with spaces 29 | VBIC.U8 Q0, Q0, Q2 @ kill the bit that makes it lowercase 30 | VSTM R1!, {Q0} @ store character to output str 31 | SUBS R3, #1 @ decrement loop counter and set flags 32 | BNE loop @ loop if character isn't null 33 | MOV R0, #(N*16) @ get the length by subtracting the pointers 34 | BX LR @ Return to caller 35 | .data 36 | aaas: .fill 16, 1, 'a' @ 16 a's 37 | endch: .fill 16, 1, 25 @ after shift, chars are 0-25 38 | spaces: .fill 16, 1, 0x20 @ spaces for bic 39 | .align 4 40 | -------------------------------------------------------------------------------- /Source Code/Chapter 14/div.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int x = 100; 6 | int y = 25; 7 | int z; 8 | 9 | z = x / y; 10 | printf("%d / %d = %d\n", x, y, z); 11 | 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /Source Code/Chapter 14/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: upper div 3 | 4 | upper: upper.c 5 | gcc -O3 -g -o upper upper.c 6 | gcc -O3 -S -fverbose-asm -g -o upper.s upper.c 7 | objdump -d upper >od.txt 8 | 9 | div: div.c 10 | gcc -march="armv8-a" -o div div.c -------------------------------------------------------------------------------- /Source Code/Chapter 14/od.txt: -------------------------------------------------------------------------------- 1 | 2 | upper: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .init: 6 | 7 | 000102c8 <_init>: 8 | 102c8: e92d4008 push {r3, lr} 9 | 102cc: eb000037 bl 103b0 10 | 102d0: e8bd8008 pop {r3, pc} 11 | 12 | Disassembly of section .plt: 13 | 14 | 000102d4 <.plt>: 15 | 102d4: e52de004 push {lr} ; (str lr, [sp, #-4]!) 16 | 102d8: e59fe004 ldr lr, [pc, #4] ; 102e4 <.plt+0x10> 17 | 102dc: e08fe00e add lr, pc, lr 18 | 102e0: e5bef008 ldr pc, [lr, #8]! 19 | 102e4: 00010d1c .word 0x00010d1c 20 | 21 | 000102e8 : 22 | 102e8: e28fc600 add ip, pc, #0, 12 23 | 102ec: e28cca10 add ip, ip, #16, 20 ; 0x10000 24 | 102f0: e5bcfd1c ldr pc, [ip, #3356]! ; 0xd1c 25 | 26 | 000102f4 <__libc_start_main@plt>: 27 | 102f4: e28fc600 add ip, pc, #0, 12 28 | 102f8: e28cca10 add ip, ip, #16, 20 ; 0x10000 29 | 102fc: e5bcfd14 ldr pc, [ip, #3348]! ; 0xd14 30 | 31 | 00010300 <__gmon_start__@plt>: 32 | 10300: e28fc600 add ip, pc, #0, 12 33 | 10304: e28cca10 add ip, ip, #16, 20 ; 0x10000 34 | 10308: e5bcfd0c ldr pc, [ip, #3340]! ; 0xd0c 35 | 36 | 0001030c : 37 | 1030c: e28fc600 add ip, pc, #0, 12 38 | 10310: e28cca10 add ip, ip, #16, 20 ; 0x10000 39 | 10314: e5bcfd04 ldr pc, [ip, #3332]! ; 0xd04 40 | 41 | Disassembly of section .text: 42 | 43 | 00010318
: 44 | 10318: e59f2048 ldr r2, [pc, #72] ; 10368 45 | 1031c: e59f3048 ldr r3, [pc, #72] ; 1036c 46 | 10320: e92d4010 push {r4, lr} 47 | 10324: e5921000 ldr r1, [r2] 48 | 10328: e1a02001 mov r2, r1 49 | 1032c: e4d24001 ldrb r4, [r2], #1 50 | 10330: e2833001 add r3, r3, #1 51 | 10334: e2440061 sub r0, r4, #97 ; 0x61 52 | 10338: e3500019 cmp r0, #25 53 | 1033c: e2440020 sub r0, r4, #32 54 | 10340: 95430001 strbls r0, [r3, #-1] 55 | 10344: 9afffff8 bls 1032c 56 | 10348: e3540000 cmp r4, #0 57 | 1034c: e5434001 strb r4, [r3, #-1] 58 | 10350: 1afffff5 bne 1032c 59 | 10354: e59f2010 ldr r2, [pc, #16] ; 1036c 60 | 10358: e59f0010 ldr r0, [pc, #16] ; 10370 61 | 1035c: ebffffe1 bl 102e8 62 | 10360: e1a00004 mov r0, r4 63 | 10364: e8bd8010 pop {r4, pc} 64 | 10368: 00021028 .word 0x00021028 65 | 1036c: 00021030 .word 0x00021030 66 | 10370: 00010504 .word 0x00010504 67 | 68 | 00010374 <_start>: 69 | 10374: e3a0b000 mov fp, #0 70 | 10378: e3a0e000 mov lr, #0 71 | 1037c: e49d1004 pop {r1} ; (ldr r1, [sp], #4) 72 | 10380: e1a0200d mov r2, sp 73 | 10384: e52d2004 push {r2} ; (str r2, [sp, #-4]!) 74 | 10388: e52d0004 push {r0} ; (str r0, [sp, #-4]!) 75 | 1038c: e59fc010 ldr ip, [pc, #16] ; 103a4 <_start+0x30> 76 | 10390: e52dc004 push {ip} ; (str ip, [sp, #-4]!) 77 | 10394: e59f000c ldr r0, [pc, #12] ; 103a8 <_start+0x34> 78 | 10398: e59f300c ldr r3, [pc, #12] ; 103ac <_start+0x38> 79 | 1039c: ebffffd4 bl 102f4 <__libc_start_main@plt> 80 | 103a0: ebffffd9 bl 1030c 81 | 103a4: 000104f4 .word 0x000104f4 82 | 103a8: 00010318 .word 0x00010318 83 | 103ac: 00010494 .word 0x00010494 84 | 85 | 000103b0 : 86 | 103b0: e59f3014 ldr r3, [pc, #20] ; 103cc 87 | 103b4: e59f2014 ldr r2, [pc, #20] ; 103d0 88 | 103b8: e08f3003 add r3, pc, r3 89 | 103bc: e7932002 ldr r2, [r3, r2] 90 | 103c0: e3520000 cmp r2, #0 91 | 103c4: 012fff1e bxeq lr 92 | 103c8: eaffffcc b 10300 <__gmon_start__@plt> 93 | 103cc: 00010c40 .word 0x00010c40 94 | 103d0: 0000001c .word 0x0000001c 95 | 96 | 000103d4 : 97 | 103d4: e59f0018 ldr r0, [pc, #24] ; 103f4 98 | 103d8: e59f3018 ldr r3, [pc, #24] ; 103f8 99 | 103dc: e1530000 cmp r3, r0 100 | 103e0: 012fff1e bxeq lr 101 | 103e4: e59f3010 ldr r3, [pc, #16] ; 103fc 102 | 103e8: e3530000 cmp r3, #0 103 | 103ec: 012fff1e bxeq lr 104 | 103f0: e12fff13 bx r3 105 | 103f4: 0002102c .word 0x0002102c 106 | 103f8: 0002102c .word 0x0002102c 107 | 103fc: 00000000 .word 0x00000000 108 | 109 | 00010400 : 110 | 10400: e59f0024 ldr r0, [pc, #36] ; 1042c 111 | 10404: e59f1024 ldr r1, [pc, #36] ; 10430 112 | 10408: e0411000 sub r1, r1, r0 113 | 1040c: e1a01141 asr r1, r1, #2 114 | 10410: e0811fa1 add r1, r1, r1, lsr #31 115 | 10414: e1b010c1 asrs r1, r1, #1 116 | 10418: 012fff1e bxeq lr 117 | 1041c: e59f3010 ldr r3, [pc, #16] ; 10434 118 | 10420: e3530000 cmp r3, #0 119 | 10424: 012fff1e bxeq lr 120 | 10428: e12fff13 bx r3 121 | 1042c: 0002102c .word 0x0002102c 122 | 10430: 0002102c .word 0x0002102c 123 | 10434: 00000000 .word 0x00000000 124 | 125 | 00010438 <__do_global_dtors_aux>: 126 | 10438: e92d4010 push {r4, lr} 127 | 1043c: e59f4018 ldr r4, [pc, #24] ; 1045c <__do_global_dtors_aux+0x24> 128 | 10440: e5d43000 ldrb r3, [r4] 129 | 10444: e3530000 cmp r3, #0 130 | 10448: 18bd8010 popne {r4, pc} 131 | 1044c: ebffffe0 bl 103d4 132 | 10450: e3a03001 mov r3, #1 133 | 10454: e5c43000 strb r3, [r4] 134 | 10458: e8bd8010 pop {r4, pc} 135 | 1045c: 0002102c .word 0x0002102c 136 | 137 | 00010460 : 138 | 10460: eaffffe6 b 10400 139 | 140 | 00010464 : 141 | 10464: e4d03001 ldrb r3, [r0], #1 142 | 10468: e2811001 add r1, r1, #1 143 | 1046c: e2432061 sub r2, r3, #97 ; 0x61 144 | 10470: e3520019 cmp r2, #25 145 | 10474: e2432020 sub r2, r3, #32 146 | 10478: 95412001 strbls r2, [r1, #-1] 147 | 1047c: 9afffff8 bls 10464 148 | 10480: e3530000 cmp r3, #0 149 | 10484: e5413001 strb r3, [r1, #-1] 150 | 10488: 1afffff5 bne 10464 151 | 1048c: e0410000 sub r0, r1, r0 152 | 10490: e12fff1e bx lr 153 | 154 | 00010494 <__libc_csu_init>: 155 | 10494: e92d47f0 push {r4, r5, r6, r7, r8, r9, sl, lr} 156 | 10498: e1a07000 mov r7, r0 157 | 1049c: e59f6048 ldr r6, [pc, #72] ; 104ec <__libc_csu_init+0x58> 158 | 104a0: e59f5048 ldr r5, [pc, #72] ; 104f0 <__libc_csu_init+0x5c> 159 | 104a4: e08f6006 add r6, pc, r6 160 | 104a8: e08f5005 add r5, pc, r5 161 | 104ac: e0466005 sub r6, r6, r5 162 | 104b0: e1a08001 mov r8, r1 163 | 104b4: e1a09002 mov r9, r2 164 | 104b8: ebffff82 bl 102c8 <_init> 165 | 104bc: e1b06146 asrs r6, r6, #2 166 | 104c0: 08bd87f0 popeq {r4, r5, r6, r7, r8, r9, sl, pc} 167 | 104c4: e3a04000 mov r4, #0 168 | 104c8: e2844001 add r4, r4, #1 169 | 104cc: e4953004 ldr r3, [r5], #4 170 | 104d0: e1a02009 mov r2, r9 171 | 104d4: e1a01008 mov r1, r8 172 | 104d8: e1a00007 mov r0, r7 173 | 104dc: e12fff33 blx r3 174 | 104e0: e1560004 cmp r6, r4 175 | 104e4: 1afffff7 bne 104c8 <__libc_csu_init+0x34> 176 | 104e8: e8bd87f0 pop {r4, r5, r6, r7, r8, r9, sl, pc} 177 | 104ec: 00010a68 .word 0x00010a68 178 | 104f0: 00010a60 .word 0x00010a60 179 | 180 | 000104f4 <__libc_csu_fini>: 181 | 104f4: e12fff1e bx lr 182 | 183 | Disassembly of section .fini: 184 | 185 | 000104f8 <_fini>: 186 | 104f8: e92d4008 push {r3, lr} 187 | 104fc: e8bd8008 pop {r3, pc} 188 | -------------------------------------------------------------------------------- /Source Code/Chapter 14/od2.txt: -------------------------------------------------------------------------------- 1 | 2 | div: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .init: 6 | 7 | 000102c8 <_init>: 8 | 102c8: e92d4008 push {r3, lr} 9 | 102cc: eb000020 bl 10354 10 | 102d0: e8bd8008 pop {r3, pc} 11 | 12 | Disassembly of section .plt: 13 | 14 | 000102d4 <.plt>: 15 | 102d4: e52de004 push {lr} ; (str lr, [sp, #-4]!) 16 | 102d8: e59fe004 ldr lr, [pc, #4] ; 102e4 <.plt+0x10> 17 | 102dc: e08fe00e add lr, pc, lr 18 | 102e0: e5bef008 ldr pc, [lr, #8]! 19 | 102e4: 00010d1c .word 0x00010d1c 20 | 21 | 000102e8 : 22 | 102e8: e28fc600 add ip, pc, #0, 12 23 | 102ec: e28cca10 add ip, ip, #16, 20 ; 0x10000 24 | 102f0: e5bcfd1c ldr pc, [ip, #3356]! ; 0xd1c 25 | 26 | 000102f4 <__libc_start_main@plt>: 27 | 102f4: e28fc600 add ip, pc, #0, 12 28 | 102f8: e28cca10 add ip, ip, #16, 20 ; 0x10000 29 | 102fc: e5bcfd14 ldr pc, [ip, #3348]! ; 0xd14 30 | 31 | 00010300 <__gmon_start__@plt>: 32 | 10300: e28fc600 add ip, pc, #0, 12 33 | 10304: e28cca10 add ip, ip, #16, 20 ; 0x10000 34 | 10308: e5bcfd0c ldr pc, [ip, #3340]! ; 0xd0c 35 | 36 | 0001030c : 37 | 1030c: e28fc600 add ip, pc, #0, 12 38 | 10310: e28cca10 add ip, ip, #16, 20 ; 0x10000 39 | 10314: e5bcfd04 ldr pc, [ip, #3332]! ; 0xd04 40 | 41 | Disassembly of section .text: 42 | 43 | 00010318 <_start>: 44 | 10318: e3a0b000 mov fp, #0 45 | 1031c: e3a0e000 mov lr, #0 46 | 10320: e49d1004 pop {r1} ; (ldr r1, [sp], #4) 47 | 10324: e1a0200d mov r2, sp 48 | 10328: e52d2004 push {r2} ; (str r2, [sp, #-4]!) 49 | 1032c: e52d0004 push {r0} ; (str r0, [sp, #-4]!) 50 | 10330: e59fc010 ldr ip, [pc, #16] ; 10348 <_start+0x30> 51 | 10334: e52dc004 push {ip} ; (str ip, [sp, #-4]!) 52 | 10338: e59f000c ldr r0, [pc, #12] ; 1034c <_start+0x34> 53 | 1033c: e59f300c ldr r3, [pc, #12] ; 10350 <_start+0x38> 54 | 10340: ebffffeb bl 102f4 <__libc_start_main@plt> 55 | 10344: ebfffff0 bl 1030c 56 | 10348: 0001048c .word 0x0001048c 57 | 1034c: 00010408 .word 0x00010408 58 | 10350: 0001042c .word 0x0001042c 59 | 60 | 00010354 : 61 | 10354: e59f3014 ldr r3, [pc, #20] ; 10370 62 | 10358: e59f2014 ldr r2, [pc, #20] ; 10374 63 | 1035c: e08f3003 add r3, pc, r3 64 | 10360: e7932002 ldr r2, [r3, r2] 65 | 10364: e3520000 cmp r2, #0 66 | 10368: 012fff1e bxeq lr 67 | 1036c: eaffffe3 b 10300 <__gmon_start__@plt> 68 | 10370: 00010c9c .word 0x00010c9c 69 | 10374: 0000001c .word 0x0000001c 70 | 71 | 00010378 : 72 | 10378: e59f0018 ldr r0, [pc, #24] ; 10398 73 | 1037c: e59f3018 ldr r3, [pc, #24] ; 1039c 74 | 10380: e1530000 cmp r3, r0 75 | 10384: 012fff1e bxeq lr 76 | 10388: e59f3010 ldr r3, [pc, #16] ; 103a0 77 | 1038c: e3530000 cmp r3, #0 78 | 10390: 012fff1e bxeq lr 79 | 10394: e12fff13 bx r3 80 | 10398: 00021028 .word 0x00021028 81 | 1039c: 00021028 .word 0x00021028 82 | 103a0: 00000000 .word 0x00000000 83 | 84 | 000103a4 : 85 | 103a4: e59f0024 ldr r0, [pc, #36] ; 103d0 86 | 103a8: e59f1024 ldr r1, [pc, #36] ; 103d4 87 | 103ac: e0411000 sub r1, r1, r0 88 | 103b0: e1a01141 asr r1, r1, #2 89 | 103b4: e0811fa1 add r1, r1, r1, lsr #31 90 | 103b8: e1b010c1 asrs r1, r1, #1 91 | 103bc: 012fff1e bxeq lr 92 | 103c0: e59f3010 ldr r3, [pc, #16] ; 103d8 93 | 103c4: e3530000 cmp r3, #0 94 | 103c8: 012fff1e bxeq lr 95 | 103cc: e12fff13 bx r3 96 | 103d0: 00021028 .word 0x00021028 97 | 103d4: 00021028 .word 0x00021028 98 | 103d8: 00000000 .word 0x00000000 99 | 100 | 000103dc <__do_global_dtors_aux>: 101 | 103dc: e92d4010 push {r4, lr} 102 | 103e0: e59f4018 ldr r4, [pc, #24] ; 10400 <__do_global_dtors_aux+0x24> 103 | 103e4: e5d43000 ldrb r3, [r4] 104 | 103e8: e3530000 cmp r3, #0 105 | 103ec: 18bd8010 popne {r4, pc} 106 | 103f0: ebffffe0 bl 10378 107 | 103f4: e3a03001 mov r3, #1 108 | 103f8: e5c43000 strb r3, [r4] 109 | 103fc: e8bd8010 pop {r4, pc} 110 | 10400: 00021028 .word 0x00021028 111 | 112 | 00010404 : 113 | 10404: eaffffe6 b 103a4 114 | 115 | 00010408
: 116 | 10408: e92d4010 push {r4, lr} 117 | 1040c: e3a03004 mov r3, #4 118 | 10410: e3a02019 mov r2, #25 119 | 10414: e3a01064 mov r1, #100 ; 0x64 120 | 10418: e300049c movw r0, #1180 ; 0x49c 121 | 1041c: e3400001 movt r0, #1 122 | 10420: ebffffb0 bl 102e8 123 | 10424: e3a00000 mov r0, #0 124 | 10428: e8bd8010 pop {r4, pc} 125 | 126 | 0001042c <__libc_csu_init>: 127 | 1042c: e92d47f0 push {r4, r5, r6, r7, r8, r9, sl, lr} 128 | 10430: e1a07000 mov r7, r0 129 | 10434: e59f6048 ldr r6, [pc, #72] ; 10484 <__libc_csu_init+0x58> 130 | 10438: e59f5048 ldr r5, [pc, #72] ; 10488 <__libc_csu_init+0x5c> 131 | 1043c: e08f6006 add r6, pc, r6 132 | 10440: e08f5005 add r5, pc, r5 133 | 10444: e0466005 sub r6, r6, r5 134 | 10448: e1a08001 mov r8, r1 135 | 1044c: e1a09002 mov r9, r2 136 | 10450: ebffff9c bl 102c8 <_init> 137 | 10454: e1b06146 asrs r6, r6, #2 138 | 10458: 08bd87f0 popeq {r4, r5, r6, r7, r8, r9, sl, pc} 139 | 1045c: e3a04000 mov r4, #0 140 | 10460: e2844001 add r4, r4, #1 141 | 10464: e4953004 ldr r3, [r5], #4 142 | 10468: e1a02009 mov r2, r9 143 | 1046c: e1a01008 mov r1, r8 144 | 10470: e1a00007 mov r0, r7 145 | 10474: e12fff33 blx r3 146 | 10478: e1560004 cmp r6, r4 147 | 1047c: 1afffff7 bne 10460 <__libc_csu_init+0x34> 148 | 10480: e8bd87f0 pop {r4, r5, r6, r7, r8, r9, sl, pc} 149 | 10484: 00010ad0 .word 0x00010ad0 150 | 10488: 00010ac8 .word 0x00010ac8 151 | 152 | 0001048c <__libc_csu_fini>: 153 | 1048c: e12fff1e bx lr 154 | 155 | Disassembly of section .fini: 156 | 157 | 00010490 <_fini>: 158 | 10490: e92d4008 push {r3, lr} 159 | 10494: e8bd8008 pop {r3, pc} 160 | -------------------------------------------------------------------------------- /Source Code/Chapter 14/upper.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int mytoupper(char *instr, char *outstr) 4 | { 5 | char cur; 6 | 7 | do 8 | { 9 | cur = *instr; 10 | if ((cur >= 'a') && (cur <='z')) 11 | { 12 | cur = cur - ('a'-'A'); 13 | } 14 | *outstr++ = cur; 15 | instr++; 16 | } while (cur != '\0'); 17 | return( outstr - instr ); 18 | } 19 | 20 | #define BUFFERSIZE 250 21 | 22 | char *tstStr = "This is a test!"; 23 | char outStr[BUFFERSIZE]; 24 | 25 | int main() 26 | { 27 | mytoupper(tstStr, outStr); 28 | printf("Input: %s\nOutput: %s\n", tstStr, outStr); 29 | 30 | return(0); 31 | } 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 14/upper.s: -------------------------------------------------------------------------------- 1 | .arch armv6 2 | .eabi_attribute 28, 1 @ Tag_ABI_VFP_args 3 | .eabi_attribute 20, 1 @ Tag_ABI_FP_denormal 4 | .eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions 5 | .eabi_attribute 23, 3 @ Tag_ABI_FP_number_model 6 | .eabi_attribute 24, 1 @ Tag_ABI_align8_needed 7 | .eabi_attribute 25, 1 @ Tag_ABI_align8_preserved 8 | .eabi_attribute 26, 2 @ Tag_ABI_enum_size 9 | .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals 10 | .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access 11 | .eabi_attribute 18, 4 @ Tag_ABI_PCS_wchar_t 12 | .file "upper.c" 13 | @ GNU C17 (Raspbian 8.3.0-6+rpi1) version 8.3.0 (arm-linux-gnueabihf) 14 | @ compiled by GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.20-GMP 15 | 16 | @ GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 17 | @ options passed: -imultilib . -imultiarch arm-linux-gnueabihf upper.c 18 | @ -mfloat-abi=hard -mfpu=vfp -mtls-dialect=gnu -marm -march=armv6+fp 19 | @ -auxbase-strip upper.s -g -O3 -fverbose-asm 20 | @ options enabled: -faggressive-loop-optimizations -falign-jumps 21 | @ -falign-labels -falign-loops -fauto-inc-dec -fbranch-count-reg 22 | @ -fcaller-saves -fchkp-check-incomplete-type -fchkp-check-read 23 | @ -fchkp-check-write -fchkp-instrument-calls -fchkp-narrow-bounds 24 | @ -fchkp-optimize -fchkp-store-bounds -fchkp-use-static-bounds 25 | @ -fchkp-use-static-const-bounds -fchkp-use-wrappers -fcode-hoisting 26 | @ -fcombine-stack-adjustments -fcommon -fcompare-elim -fcprop-registers 27 | @ -fcrossjumping -fcse-follow-jumps -fdefer-pop 28 | @ -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively 29 | @ -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types 30 | @ -fexpensive-optimizations -fforward-propagate -ffp-int-builtin-inexact 31 | @ -ffunction-cse -fgcse -fgcse-after-reload -fgcse-lm -fgnu-runtime 32 | @ -fgnu-unique -fguess-branch-probability -fhoist-adjacent-loads -fident 33 | @ -fif-conversion -fif-conversion2 -findirect-inlining -finline 34 | @ -finline-atomics -finline-functions -finline-functions-called-once 35 | @ -finline-small-functions -fipa-bit-cp -fipa-cp -fipa-cp-clone -fipa-icf 36 | @ -fipa-icf-functions -fipa-icf-variables -fipa-profile -fipa-pure-const 37 | @ -fipa-ra -fipa-reference -fipa-sra -fipa-vrp -fira-hoist-pressure 38 | @ -fira-share-save-slots -fira-share-spill-slots 39 | @ -fisolate-erroneous-paths-dereference -fivopts -fkeep-static-consts 40 | @ -fleading-underscore -flifetime-dse -floop-interchange 41 | @ -floop-unroll-and-jam -flra-remat -flto-odr-type-merging -fmath-errno 42 | @ -fmerge-constants -fmerge-debug-strings -fmove-loop-invariants 43 | @ -fomit-frame-pointer -foptimize-sibling-calls -foptimize-strlen 44 | @ -fpartial-inlining -fpeel-loops -fpeephole -fpeephole2 -fplt 45 | @ -fpredictive-commoning -fprefetch-loop-arrays -freg-struct-return 46 | @ -freorder-blocks -freorder-functions -frerun-cse-after-loop 47 | @ -fsched-critical-path-heuristic -fsched-dep-count-heuristic 48 | @ -fsched-group-heuristic -fsched-interblock -fsched-last-insn-heuristic 49 | @ -fsched-pressure -fsched-rank-heuristic -fsched-spec 50 | @ -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fschedule-insns 51 | @ -fschedule-insns2 -fsection-anchors -fsemantic-interposition 52 | @ -fshow-column -fshrink-wrap -fshrink-wrap-separate -fsigned-zeros 53 | @ -fsplit-ivs-in-unroller -fsplit-loops -fsplit-paths -fsplit-wide-types 54 | @ -fssa-backprop -fssa-phiopt -fstdarg-opt -fstore-merging 55 | @ -fstrict-aliasing -fstrict-volatile-bitfields -fsync-libcalls 56 | @ -fthread-jumps -ftoplevel-reorder -ftrapping-math -ftree-bit-ccp 57 | @ -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-coalesce-vars 58 | @ -ftree-copy-prop -ftree-cselim -ftree-dce -ftree-dominator-opts 59 | @ -ftree-dse -ftree-forwprop -ftree-fre -ftree-loop-distribute-patterns 60 | @ -ftree-loop-distribution -ftree-loop-if-convert -ftree-loop-im 61 | @ -ftree-loop-ivcanon -ftree-loop-optimize -ftree-loop-vectorize 62 | @ -ftree-parallelize-loops= -ftree-partial-pre -ftree-phiprop -ftree-pre 63 | @ -ftree-pta -ftree-reassoc -ftree-scev-cprop -ftree-sink 64 | @ -ftree-slp-vectorize -ftree-slsr -ftree-sra -ftree-switch-conversion 65 | @ -ftree-tail-merge -ftree-ter -ftree-vrp -funit-at-a-time -funswitch-loops 66 | @ -fvar-tracking -fvar-tracking-assignments -fverbose-asm 67 | @ -fzero-initialized-in-bss -marm -mbe32 -mglibc -mlittle-endian 68 | @ -mpic-data-is-text-relative -msched-prolog -munaligned-access 69 | @ -mvectorize-with-neon-quad 70 | 71 | .text 72 | .Ltext0: 73 | .cfi_sections .debug_frame 74 | .align 2 75 | .global mytoupper 76 | .arch armv6 77 | .syntax unified 78 | .arm 79 | .fpu vfp 80 | .type mytoupper, %function 81 | mytoupper: 82 | .LFB11: 83 | .file 1 "upper.c" 84 | .loc 1 4 1 view -0 85 | .cfi_startproc 86 | @ args = 0, pretend = 0, frame = 0 87 | @ frame_needed = 0, uses_anonymous_args = 0 88 | @ link register save eliminated. 89 | .L2: 90 | .LVL0: 91 | .loc 1 5 2 view .LVU1 92 | .loc 1 7 2 view .LVU2 93 | .loc 1 9 3 view .LVU3 94 | .loc 1 12 4 view .LVU4 95 | @ upper.c:9: cur = *instr; 96 | .loc 1 9 7 is_stmt 0 view .LVU5 97 | ldrb r3, [r0], #1 @ zero_extendqisi2 @ cur, MEM[base: _2, offset: 0B] 98 | .LVL1: 99 | .loc 1 10 3 is_stmt 1 view .LVU6 100 | .loc 1 14 3 view .LVU7 101 | .loc 1 14 3 view .LVU8 102 | add r1, r1, #1 @ outstr, outstr, 103 | .LVL2: 104 | @ upper.c:10: if ((cur >= 'a') && (cur <='z')) 105 | .loc 1 10 6 is_stmt 0 view .LVU9 106 | sub r2, r3, #97 @ tmp120, cur, 107 | cmp r2, #25 @ tmp120, 108 | @ upper.c:12: cur = cur - ('a'-'A'); 109 | .loc 1 12 8 view .LVU10 110 | sub r2, r3, #32 @ tmp121, cur, 111 | @ upper.c:14: *outstr++ = cur; 112 | .loc 1 14 13 view .LVU11 113 | strbls r2, [r1, #-1] @ tmp121, MEM[base: _17, offset: 4294967295B] 114 | @ upper.c:10: if ((cur >= 'a') && (cur <='z')) 115 | .loc 1 10 6 view .LVU12 116 | bls .L2 @, 117 | @ upper.c:16: } while (cur != '\0'); 118 | .loc 1 16 2 view .LVU13 119 | cmp r3, #0 @ cur, 120 | @ upper.c:14: *outstr++ = cur; 121 | .loc 1 14 13 view .LVU14 122 | strb r3, [r1, #-1] @ cur, MEM[base: _17, offset: 4294967295B] 123 | .loc 1 15 3 is_stmt 1 view .LVU15 124 | .LVL3: 125 | @ upper.c:16: } while (cur != '\0'); 126 | .loc 1 16 2 is_stmt 0 view .LVU16 127 | bne .L2 @, 128 | .loc 1 17 2 is_stmt 1 view .LVU17 129 | @ upper.c:18: } 130 | .loc 1 18 1 is_stmt 0 view .LVU18 131 | sub r0, r1, r0 @, outstr, ivtmp.9 132 | bx lr @ 133 | .cfi_endproc 134 | .LFE11: 135 | .size mytoupper, .-mytoupper 136 | .section .text.startup,"ax",%progbits 137 | .align 2 138 | .global main 139 | .syntax unified 140 | .arm 141 | .fpu vfp 142 | .type main, %function 143 | main: 144 | .LFB12: 145 | .loc 1 26 1 is_stmt 1 view -0 146 | .cfi_startproc 147 | @ args = 0, pretend = 0, frame = 0 148 | @ frame_needed = 0, uses_anonymous_args = 0 149 | .loc 1 27 2 view .LVU20 150 | ldr r2, .L11 @ tmp117, 151 | ldr r3, .L11+4 @ outstr, 152 | @ upper.c:26: { 153 | .loc 1 26 1 is_stmt 0 view .LVU21 154 | push {r4, lr} @ 155 | .cfi_def_cfa_offset 8 156 | .cfi_offset 4, -8 157 | .cfi_offset 14, -4 158 | @ upper.c:27: mytoupper(tstStr, outStr); 159 | .loc 1 27 2 view .LVU22 160 | ldr r1, [r2] @ tstStr.1_1, tstStr 161 | .LVL4: 162 | .LBB4: 163 | .LBI4: 164 | .loc 1 3 5 is_stmt 1 view .LVU23 165 | .LBE4: 166 | @ upper.c:27: mytoupper(tstStr, outStr); 167 | .loc 1 27 2 is_stmt 0 view .LVU24 168 | mov r2, r1 @ instr, tstStr.1_1 169 | .LVL5: 170 | .L7: 171 | .LBB6: 172 | .LBB5: 173 | .loc 1 5 2 is_stmt 1 view .LVU25 174 | .loc 1 7 2 view .LVU26 175 | .loc 1 9 3 view .LVU27 176 | .loc 1 12 4 view .LVU28 177 | @ upper.c:9: cur = *instr; 178 | .loc 1 9 7 is_stmt 0 view .LVU29 179 | ldrb r4, [r2], #1 @ zero_extendqisi2 @ cur, MEM[base: instr_4, offset: 0B] 180 | .LVL6: 181 | .loc 1 10 3 is_stmt 1 view .LVU30 182 | .loc 1 14 3 view .LVU31 183 | .loc 1 14 3 view .LVU32 184 | add r3, r3, #1 @ outstr, outstr, 185 | .LVL7: 186 | @ upper.c:10: if ((cur >= 'a') && (cur <='z')) 187 | .loc 1 10 6 is_stmt 0 view .LVU33 188 | sub r0, r4, #97 @ tmp119, cur, 189 | cmp r0, #25 @ tmp119, 190 | @ upper.c:12: cur = cur - ('a'-'A'); 191 | .loc 1 12 8 view .LVU34 192 | sub r0, r4, #32 @ tmp120, cur, 193 | @ upper.c:14: *outstr++ = cur; 194 | .loc 1 14 13 view .LVU35 195 | strbls r0, [r3, #-1] @ tmp120, MEM[base: _14, offset: 4294967295B] 196 | @ upper.c:10: if ((cur >= 'a') && (cur <='z')) 197 | .loc 1 10 6 view .LVU36 198 | bls .L7 @, 199 | @ upper.c:16: } while (cur != '\0'); 200 | .loc 1 16 2 view .LVU37 201 | cmp r4, #0 @ cur, 202 | @ upper.c:14: *outstr++ = cur; 203 | .loc 1 14 13 view .LVU38 204 | strb r4, [r3, #-1] @ cur, MEM[base: _14, offset: 4294967295B] 205 | .loc 1 15 3 is_stmt 1 view .LVU39 206 | .LVL8: 207 | @ upper.c:16: } while (cur != '\0'); 208 | .loc 1 16 2 is_stmt 0 view .LVU40 209 | bne .L7 @, 210 | .loc 1 17 2 is_stmt 1 view .LVU41 211 | .LVL9: 212 | .loc 1 17 2 is_stmt 0 view .LVU42 213 | .LBE5: 214 | .LBE6: 215 | .loc 1 28 2 is_stmt 1 view .LVU43 216 | ldr r2, .L11+4 @, 217 | ldr r0, .L11+8 @, 218 | bl printf @ 219 | .LVL10: 220 | .loc 1 30 2 view .LVU44 221 | @ upper.c:31: } 222 | .loc 1 31 1 is_stmt 0 view .LVU45 223 | mov r0, r4 @, cur 224 | pop {r4, pc} @ 225 | .L12: 226 | .align 2 227 | .L11: 228 | .word .LANCHOR0 229 | .word outStr 230 | .word .LC0 231 | .cfi_endproc 232 | .LFE12: 233 | .size main, .-main 234 | .comm outStr,250,4 235 | .global tstStr 236 | .data 237 | .align 2 238 | .set .LANCHOR0,. + 0 239 | .type tstStr, %object 240 | .size tstStr, 4 241 | tstStr: 242 | .word .LC1 243 | .section .rodata.str1.4,"aMS",%progbits,1 244 | .align 2 245 | .LC0: 246 | .ascii "Input: %s\012Output: %s\012\000" 247 | .space 2 248 | .LC1: 249 | .ascii "This is a test!\000" 250 | .text 251 | .Letext0: 252 | .file 2 "/usr/lib/gcc/arm-linux-gnueabihf/8/include/stddef.h" 253 | .file 3 "/usr/include/arm-linux-gnueabihf/bits/types.h" 254 | .file 4 "/usr/include/arm-linux-gnueabihf/bits/types/struct_FILE.h" 255 | .file 5 "/usr/include/arm-linux-gnueabihf/bits/types/FILE.h" 256 | .file 6 "/usr/include/stdio.h" 257 | .file 7 "/usr/include/arm-linux-gnueabihf/bits/sys_errlist.h" 258 | .section .debug_info,"",%progbits 259 | .Ldebug_info0: 260 | .4byte 0x421 261 | .2byte 0x4 262 | .4byte .Ldebug_abbrev0 263 | .byte 0x4 264 | .uleb128 0x1 265 | .4byte .LASF56 266 | .byte 0xc 267 | .4byte .LASF57 268 | .4byte .LASF58 269 | .4byte .Ldebug_ranges0+0x18 270 | .4byte 0 271 | .4byte .Ldebug_line0 272 | .uleb128 0x2 273 | .4byte .LASF8 274 | .byte 0x2 275 | .byte 0xd8 276 | .byte 0x17 277 | .4byte 0x31 278 | .uleb128 0x3 279 | .byte 0x4 280 | .byte 0x7 281 | .4byte .LASF0 282 | .uleb128 0x4 283 | .byte 0x4 284 | .uleb128 0x3 285 | .byte 0x1 286 | .byte 0x8 287 | .4byte .LASF1 288 | .uleb128 0x3 289 | .byte 0x2 290 | .byte 0x7 291 | .4byte .LASF2 292 | .uleb128 0x3 293 | .byte 0x4 294 | .byte 0x7 295 | .4byte .LASF3 296 | .uleb128 0x3 297 | .byte 0x1 298 | .byte 0x6 299 | .4byte .LASF4 300 | .uleb128 0x3 301 | .byte 0x2 302 | .byte 0x5 303 | .4byte .LASF5 304 | .uleb128 0x5 305 | .byte 0x4 306 | .byte 0x5 307 | .ascii "int\000" 308 | .uleb128 0x3 309 | .byte 0x8 310 | .byte 0x5 311 | .4byte .LASF6 312 | .uleb128 0x3 313 | .byte 0x8 314 | .byte 0x7 315 | .4byte .LASF7 316 | .uleb128 0x2 317 | .4byte .LASF9 318 | .byte 0x3 319 | .byte 0x41 320 | .byte 0x25 321 | .4byte 0x64 322 | .uleb128 0x2 323 | .4byte .LASF10 324 | .byte 0x3 325 | .byte 0x96 326 | .byte 0x19 327 | .4byte 0x8a 328 | .uleb128 0x3 329 | .byte 0x4 330 | .byte 0x5 331 | .4byte .LASF11 332 | .uleb128 0x2 333 | .4byte .LASF12 334 | .byte 0x3 335 | .byte 0x97 336 | .byte 0x1b 337 | .4byte 0x72 338 | .uleb128 0x6 339 | .byte 0x4 340 | .4byte 0xa3 341 | .uleb128 0x3 342 | .byte 0x1 343 | .byte 0x8 344 | .4byte .LASF13 345 | .uleb128 0x7 346 | .4byte 0xa3 347 | .uleb128 0x8 348 | .4byte .LASF59 349 | .byte 0x98 350 | .byte 0x4 351 | .byte 0x31 352 | .byte 0x8 353 | .4byte 0x236 354 | .uleb128 0x9 355 | .4byte .LASF14 356 | .byte 0x4 357 | .byte 0x33 358 | .byte 0x7 359 | .4byte 0x5d 360 | .byte 0 361 | .uleb128 0x9 362 | .4byte .LASF15 363 | .byte 0x4 364 | .byte 0x36 365 | .byte 0x9 366 | .4byte 0x9d 367 | .byte 0x4 368 | .uleb128 0x9 369 | .4byte .LASF16 370 | .byte 0x4 371 | .byte 0x37 372 | .byte 0x9 373 | .4byte 0x9d 374 | .byte 0x8 375 | .uleb128 0x9 376 | .4byte .LASF17 377 | .byte 0x4 378 | .byte 0x38 379 | .byte 0x9 380 | .4byte 0x9d 381 | .byte 0xc 382 | .uleb128 0x9 383 | .4byte .LASF18 384 | .byte 0x4 385 | .byte 0x39 386 | .byte 0x9 387 | .4byte 0x9d 388 | .byte 0x10 389 | .uleb128 0x9 390 | .4byte .LASF19 391 | .byte 0x4 392 | .byte 0x3a 393 | .byte 0x9 394 | .4byte 0x9d 395 | .byte 0x14 396 | .uleb128 0x9 397 | .4byte .LASF20 398 | .byte 0x4 399 | .byte 0x3b 400 | .byte 0x9 401 | .4byte 0x9d 402 | .byte 0x18 403 | .uleb128 0x9 404 | .4byte .LASF21 405 | .byte 0x4 406 | .byte 0x3c 407 | .byte 0x9 408 | .4byte 0x9d 409 | .byte 0x1c 410 | .uleb128 0x9 411 | .4byte .LASF22 412 | .byte 0x4 413 | .byte 0x3d 414 | .byte 0x9 415 | .4byte 0x9d 416 | .byte 0x20 417 | .uleb128 0x9 418 | .4byte .LASF23 419 | .byte 0x4 420 | .byte 0x40 421 | .byte 0x9 422 | .4byte 0x9d 423 | .byte 0x24 424 | .uleb128 0x9 425 | .4byte .LASF24 426 | .byte 0x4 427 | .byte 0x41 428 | .byte 0x9 429 | .4byte 0x9d 430 | .byte 0x28 431 | .uleb128 0x9 432 | .4byte .LASF25 433 | .byte 0x4 434 | .byte 0x42 435 | .byte 0x9 436 | .4byte 0x9d 437 | .byte 0x2c 438 | .uleb128 0x9 439 | .4byte .LASF26 440 | .byte 0x4 441 | .byte 0x44 442 | .byte 0x16 443 | .4byte 0x24f 444 | .byte 0x30 445 | .uleb128 0x9 446 | .4byte .LASF27 447 | .byte 0x4 448 | .byte 0x46 449 | .byte 0x14 450 | .4byte 0x255 451 | .byte 0x34 452 | .uleb128 0x9 453 | .4byte .LASF28 454 | .byte 0x4 455 | .byte 0x48 456 | .byte 0x7 457 | .4byte 0x5d 458 | .byte 0x38 459 | .uleb128 0x9 460 | .4byte .LASF29 461 | .byte 0x4 462 | .byte 0x49 463 | .byte 0x7 464 | .4byte 0x5d 465 | .byte 0x3c 466 | .uleb128 0x9 467 | .4byte .LASF30 468 | .byte 0x4 469 | .byte 0x4a 470 | .byte 0xb 471 | .4byte 0x7e 472 | .byte 0x40 473 | .uleb128 0x9 474 | .4byte .LASF31 475 | .byte 0x4 476 | .byte 0x4d 477 | .byte 0x12 478 | .4byte 0x41 479 | .byte 0x44 480 | .uleb128 0x9 481 | .4byte .LASF32 482 | .byte 0x4 483 | .byte 0x4e 484 | .byte 0xf 485 | .4byte 0x4f 486 | .byte 0x46 487 | .uleb128 0x9 488 | .4byte .LASF33 489 | .byte 0x4 490 | .byte 0x4f 491 | .byte 0x8 492 | .4byte 0x25b 493 | .byte 0x47 494 | .uleb128 0x9 495 | .4byte .LASF34 496 | .byte 0x4 497 | .byte 0x51 498 | .byte 0xf 499 | .4byte 0x26b 500 | .byte 0x48 501 | .uleb128 0x9 502 | .4byte .LASF35 503 | .byte 0x4 504 | .byte 0x59 505 | .byte 0xd 506 | .4byte 0x91 507 | .byte 0x50 508 | .uleb128 0x9 509 | .4byte .LASF36 510 | .byte 0x4 511 | .byte 0x5b 512 | .byte 0x17 513 | .4byte 0x276 514 | .byte 0x58 515 | .uleb128 0x9 516 | .4byte .LASF37 517 | .byte 0x4 518 | .byte 0x5c 519 | .byte 0x19 520 | .4byte 0x281 521 | .byte 0x5c 522 | .uleb128 0x9 523 | .4byte .LASF38 524 | .byte 0x4 525 | .byte 0x5d 526 | .byte 0x14 527 | .4byte 0x255 528 | .byte 0x60 529 | .uleb128 0x9 530 | .4byte .LASF39 531 | .byte 0x4 532 | .byte 0x5e 533 | .byte 0x9 534 | .4byte 0x38 535 | .byte 0x64 536 | .uleb128 0x9 537 | .4byte .LASF40 538 | .byte 0x4 539 | .byte 0x5f 540 | .byte 0xa 541 | .4byte 0x25 542 | .byte 0x68 543 | .uleb128 0x9 544 | .4byte .LASF41 545 | .byte 0x4 546 | .byte 0x60 547 | .byte 0x7 548 | .4byte 0x5d 549 | .byte 0x6c 550 | .uleb128 0x9 551 | .4byte .LASF42 552 | .byte 0x4 553 | .byte 0x62 554 | .byte 0x8 555 | .4byte 0x287 556 | .byte 0x70 557 | .byte 0 558 | .uleb128 0x2 559 | .4byte .LASF43 560 | .byte 0x5 561 | .byte 0x7 562 | .byte 0x19 563 | .4byte 0xaf 564 | .uleb128 0xa 565 | .4byte .LASF60 566 | .byte 0x4 567 | .byte 0x2b 568 | .byte 0xe 569 | .uleb128 0xb 570 | .4byte .LASF44 571 | .uleb128 0x6 572 | .byte 0x4 573 | .4byte 0x24a 574 | .uleb128 0x6 575 | .byte 0x4 576 | .4byte 0xaf 577 | .uleb128 0xc 578 | .4byte 0xa3 579 | .4byte 0x26b 580 | .uleb128 0xd 581 | .4byte 0x31 582 | .byte 0 583 | .byte 0 584 | .uleb128 0x6 585 | .byte 0x4 586 | .4byte 0x242 587 | .uleb128 0xb 588 | .4byte .LASF45 589 | .uleb128 0x6 590 | .byte 0x4 591 | .4byte 0x271 592 | .uleb128 0xb 593 | .4byte .LASF46 594 | .uleb128 0x6 595 | .byte 0x4 596 | .4byte 0x27c 597 | .uleb128 0xc 598 | .4byte 0xa3 599 | .4byte 0x297 600 | .uleb128 0xd 601 | .4byte 0x31 602 | .byte 0x27 603 | .byte 0 604 | .uleb128 0xe 605 | .4byte .LASF47 606 | .byte 0x6 607 | .byte 0x89 608 | .byte 0xe 609 | .4byte 0x2a3 610 | .uleb128 0x6 611 | .byte 0x4 612 | .4byte 0x236 613 | .uleb128 0xe 614 | .4byte .LASF48 615 | .byte 0x6 616 | .byte 0x8a 617 | .byte 0xe 618 | .4byte 0x2a3 619 | .uleb128 0xe 620 | .4byte .LASF49 621 | .byte 0x6 622 | .byte 0x8b 623 | .byte 0xe 624 | .4byte 0x2a3 625 | .uleb128 0xe 626 | .4byte .LASF50 627 | .byte 0x7 628 | .byte 0x1a 629 | .byte 0xc 630 | .4byte 0x5d 631 | .uleb128 0xc 632 | .4byte 0x2e3 633 | .4byte 0x2d8 634 | .uleb128 0xf 635 | .byte 0 636 | .uleb128 0x7 637 | .4byte 0x2cd 638 | .uleb128 0x6 639 | .byte 0x4 640 | .4byte 0xaa 641 | .uleb128 0x7 642 | .4byte 0x2dd 643 | .uleb128 0xe 644 | .4byte .LASF51 645 | .byte 0x7 646 | .byte 0x1b 647 | .byte 0x1a 648 | .4byte 0x2d8 649 | .uleb128 0x10 650 | .4byte .LASF52 651 | .byte 0x1 652 | .byte 0x16 653 | .byte 0x7 654 | .4byte 0x9d 655 | .uleb128 0x5 656 | .byte 0x3 657 | .4byte tstStr 658 | .uleb128 0xc 659 | .4byte 0xa3 660 | .4byte 0x316 661 | .uleb128 0xd 662 | .4byte 0x31 663 | .byte 0xf9 664 | .byte 0 665 | .uleb128 0x10 666 | .4byte .LASF53 667 | .byte 0x1 668 | .byte 0x17 669 | .byte 0x6 670 | .4byte 0x306 671 | .uleb128 0x5 672 | .byte 0x3 673 | .4byte outStr 674 | .uleb128 0x11 675 | .4byte .LASF61 676 | .byte 0x1 677 | .byte 0x19 678 | .byte 0x5 679 | .4byte 0x5d 680 | .4byte .LFB12 681 | .4byte .LFE12-.LFB12 682 | .uleb128 0x1 683 | .byte 0x9c 684 | .4byte 0x3a6 685 | .uleb128 0x12 686 | .4byte 0x3a6 687 | .4byte .LBI4 688 | .byte .LVU23 689 | .4byte .Ldebug_ranges0+0 690 | .byte 0x1 691 | .byte 0x1b 692 | .byte 0x2 693 | .4byte 0x389 694 | .uleb128 0x13 695 | .4byte 0x3c3 696 | .4byte .LLST3 697 | .4byte .LVUS3 698 | .uleb128 0x13 699 | .4byte 0x3b7 700 | .4byte .LLST4 701 | .4byte .LVUS4 702 | .uleb128 0x14 703 | .4byte .LBB5 704 | .4byte .LBE5-.LBB5 705 | .uleb128 0x15 706 | .4byte 0x3cf 707 | .4byte .LLST5 708 | .4byte .LVUS5 709 | .byte 0 710 | .byte 0 711 | .uleb128 0x16 712 | .4byte .LVL10 713 | .4byte 0x417 714 | .uleb128 0x17 715 | .uleb128 0x1 716 | .byte 0x50 717 | .uleb128 0x5 718 | .byte 0x3 719 | .4byte .LC0 720 | .uleb128 0x17 721 | .uleb128 0x1 722 | .byte 0x52 723 | .uleb128 0x5 724 | .byte 0x3 725 | .4byte outStr 726 | .byte 0 727 | .byte 0 728 | .uleb128 0x18 729 | .4byte .LASF62 730 | .byte 0x1 731 | .byte 0x3 732 | .byte 0x5 733 | .4byte 0x5d 734 | .byte 0x1 735 | .4byte 0x3dc 736 | .uleb128 0x19 737 | .4byte .LASF54 738 | .byte 0x1 739 | .byte 0x3 740 | .byte 0x15 741 | .4byte 0x9d 742 | .uleb128 0x19 743 | .4byte .LASF55 744 | .byte 0x1 745 | .byte 0x3 746 | .byte 0x22 747 | .4byte 0x9d 748 | .uleb128 0x1a 749 | .ascii "cur\000" 750 | .byte 0x1 751 | .byte 0x5 752 | .byte 0x7 753 | .4byte 0xa3 754 | .byte 0 755 | .uleb128 0x1b 756 | .4byte 0x3a6 757 | .4byte .LFB11 758 | .4byte .LFE11-.LFB11 759 | .uleb128 0x1 760 | .byte 0x9c 761 | .4byte 0x417 762 | .uleb128 0x13 763 | .4byte 0x3b7 764 | .4byte .LLST0 765 | .4byte .LVUS0 766 | .uleb128 0x13 767 | .4byte 0x3c3 768 | .4byte .LLST1 769 | .4byte .LVUS1 770 | .uleb128 0x15 771 | .4byte 0x3cf 772 | .4byte .LLST2 773 | .4byte .LVUS2 774 | .byte 0 775 | .uleb128 0x1c 776 | .4byte .LASF63 777 | .4byte .LASF63 778 | .byte 0x6 779 | .2byte 0x14c 780 | .byte 0xc 781 | .byte 0 782 | .section .debug_abbrev,"",%progbits 783 | .Ldebug_abbrev0: 784 | .uleb128 0x1 785 | .uleb128 0x11 786 | .byte 0x1 787 | .uleb128 0x25 788 | .uleb128 0xe 789 | .uleb128 0x13 790 | .uleb128 0xb 791 | .uleb128 0x3 792 | .uleb128 0xe 793 | .uleb128 0x1b 794 | .uleb128 0xe 795 | .uleb128 0x55 796 | .uleb128 0x17 797 | .uleb128 0x11 798 | .uleb128 0x1 799 | .uleb128 0x10 800 | .uleb128 0x17 801 | .byte 0 802 | .byte 0 803 | .uleb128 0x2 804 | .uleb128 0x16 805 | .byte 0 806 | .uleb128 0x3 807 | .uleb128 0xe 808 | .uleb128 0x3a 809 | .uleb128 0xb 810 | .uleb128 0x3b 811 | .uleb128 0xb 812 | .uleb128 0x39 813 | .uleb128 0xb 814 | .uleb128 0x49 815 | .uleb128 0x13 816 | .byte 0 817 | .byte 0 818 | .uleb128 0x3 819 | .uleb128 0x24 820 | .byte 0 821 | .uleb128 0xb 822 | .uleb128 0xb 823 | .uleb128 0x3e 824 | .uleb128 0xb 825 | .uleb128 0x3 826 | .uleb128 0xe 827 | .byte 0 828 | .byte 0 829 | .uleb128 0x4 830 | .uleb128 0xf 831 | .byte 0 832 | .uleb128 0xb 833 | .uleb128 0xb 834 | .byte 0 835 | .byte 0 836 | .uleb128 0x5 837 | .uleb128 0x24 838 | .byte 0 839 | .uleb128 0xb 840 | .uleb128 0xb 841 | .uleb128 0x3e 842 | .uleb128 0xb 843 | .uleb128 0x3 844 | .uleb128 0x8 845 | .byte 0 846 | .byte 0 847 | .uleb128 0x6 848 | .uleb128 0xf 849 | .byte 0 850 | .uleb128 0xb 851 | .uleb128 0xb 852 | .uleb128 0x49 853 | .uleb128 0x13 854 | .byte 0 855 | .byte 0 856 | .uleb128 0x7 857 | .uleb128 0x26 858 | .byte 0 859 | .uleb128 0x49 860 | .uleb128 0x13 861 | .byte 0 862 | .byte 0 863 | .uleb128 0x8 864 | .uleb128 0x13 865 | .byte 0x1 866 | .uleb128 0x3 867 | .uleb128 0xe 868 | .uleb128 0xb 869 | .uleb128 0xb 870 | .uleb128 0x3a 871 | .uleb128 0xb 872 | .uleb128 0x3b 873 | .uleb128 0xb 874 | .uleb128 0x39 875 | .uleb128 0xb 876 | .uleb128 0x1 877 | .uleb128 0x13 878 | .byte 0 879 | .byte 0 880 | .uleb128 0x9 881 | .uleb128 0xd 882 | .byte 0 883 | .uleb128 0x3 884 | .uleb128 0xe 885 | .uleb128 0x3a 886 | .uleb128 0xb 887 | .uleb128 0x3b 888 | .uleb128 0xb 889 | .uleb128 0x39 890 | .uleb128 0xb 891 | .uleb128 0x49 892 | .uleb128 0x13 893 | .uleb128 0x38 894 | .uleb128 0xb 895 | .byte 0 896 | .byte 0 897 | .uleb128 0xa 898 | .uleb128 0x16 899 | .byte 0 900 | .uleb128 0x3 901 | .uleb128 0xe 902 | .uleb128 0x3a 903 | .uleb128 0xb 904 | .uleb128 0x3b 905 | .uleb128 0xb 906 | .uleb128 0x39 907 | .uleb128 0xb 908 | .byte 0 909 | .byte 0 910 | .uleb128 0xb 911 | .uleb128 0x13 912 | .byte 0 913 | .uleb128 0x3 914 | .uleb128 0xe 915 | .uleb128 0x3c 916 | .uleb128 0x19 917 | .byte 0 918 | .byte 0 919 | .uleb128 0xc 920 | .uleb128 0x1 921 | .byte 0x1 922 | .uleb128 0x49 923 | .uleb128 0x13 924 | .uleb128 0x1 925 | .uleb128 0x13 926 | .byte 0 927 | .byte 0 928 | .uleb128 0xd 929 | .uleb128 0x21 930 | .byte 0 931 | .uleb128 0x49 932 | .uleb128 0x13 933 | .uleb128 0x2f 934 | .uleb128 0xb 935 | .byte 0 936 | .byte 0 937 | .uleb128 0xe 938 | .uleb128 0x34 939 | .byte 0 940 | .uleb128 0x3 941 | .uleb128 0xe 942 | .uleb128 0x3a 943 | .uleb128 0xb 944 | .uleb128 0x3b 945 | .uleb128 0xb 946 | .uleb128 0x39 947 | .uleb128 0xb 948 | .uleb128 0x49 949 | .uleb128 0x13 950 | .uleb128 0x3f 951 | .uleb128 0x19 952 | .uleb128 0x3c 953 | .uleb128 0x19 954 | .byte 0 955 | .byte 0 956 | .uleb128 0xf 957 | .uleb128 0x21 958 | .byte 0 959 | .byte 0 960 | .byte 0 961 | .uleb128 0x10 962 | .uleb128 0x34 963 | .byte 0 964 | .uleb128 0x3 965 | .uleb128 0xe 966 | .uleb128 0x3a 967 | .uleb128 0xb 968 | .uleb128 0x3b 969 | .uleb128 0xb 970 | .uleb128 0x39 971 | .uleb128 0xb 972 | .uleb128 0x49 973 | .uleb128 0x13 974 | .uleb128 0x3f 975 | .uleb128 0x19 976 | .uleb128 0x2 977 | .uleb128 0x18 978 | .byte 0 979 | .byte 0 980 | .uleb128 0x11 981 | .uleb128 0x2e 982 | .byte 0x1 983 | .uleb128 0x3f 984 | .uleb128 0x19 985 | .uleb128 0x3 986 | .uleb128 0xe 987 | .uleb128 0x3a 988 | .uleb128 0xb 989 | .uleb128 0x3b 990 | .uleb128 0xb 991 | .uleb128 0x39 992 | .uleb128 0xb 993 | .uleb128 0x49 994 | .uleb128 0x13 995 | .uleb128 0x11 996 | .uleb128 0x1 997 | .uleb128 0x12 998 | .uleb128 0x6 999 | .uleb128 0x40 1000 | .uleb128 0x18 1001 | .uleb128 0x2117 1002 | .uleb128 0x19 1003 | .uleb128 0x1 1004 | .uleb128 0x13 1005 | .byte 0 1006 | .byte 0 1007 | .uleb128 0x12 1008 | .uleb128 0x1d 1009 | .byte 0x1 1010 | .uleb128 0x31 1011 | .uleb128 0x13 1012 | .uleb128 0x52 1013 | .uleb128 0x1 1014 | .uleb128 0x2138 1015 | .uleb128 0xb 1016 | .uleb128 0x55 1017 | .uleb128 0x17 1018 | .uleb128 0x58 1019 | .uleb128 0xb 1020 | .uleb128 0x59 1021 | .uleb128 0xb 1022 | .uleb128 0x57 1023 | .uleb128 0xb 1024 | .uleb128 0x1 1025 | .uleb128 0x13 1026 | .byte 0 1027 | .byte 0 1028 | .uleb128 0x13 1029 | .uleb128 0x5 1030 | .byte 0 1031 | .uleb128 0x31 1032 | .uleb128 0x13 1033 | .uleb128 0x2 1034 | .uleb128 0x17 1035 | .uleb128 0x2137 1036 | .uleb128 0x17 1037 | .byte 0 1038 | .byte 0 1039 | .uleb128 0x14 1040 | .uleb128 0xb 1041 | .byte 0x1 1042 | .uleb128 0x11 1043 | .uleb128 0x1 1044 | .uleb128 0x12 1045 | .uleb128 0x6 1046 | .byte 0 1047 | .byte 0 1048 | .uleb128 0x15 1049 | .uleb128 0x34 1050 | .byte 0 1051 | .uleb128 0x31 1052 | .uleb128 0x13 1053 | .uleb128 0x2 1054 | .uleb128 0x17 1055 | .uleb128 0x2137 1056 | .uleb128 0x17 1057 | .byte 0 1058 | .byte 0 1059 | .uleb128 0x16 1060 | .uleb128 0x4109 1061 | .byte 0x1 1062 | .uleb128 0x11 1063 | .uleb128 0x1 1064 | .uleb128 0x31 1065 | .uleb128 0x13 1066 | .byte 0 1067 | .byte 0 1068 | .uleb128 0x17 1069 | .uleb128 0x410a 1070 | .byte 0 1071 | .uleb128 0x2 1072 | .uleb128 0x18 1073 | .uleb128 0x2111 1074 | .uleb128 0x18 1075 | .byte 0 1076 | .byte 0 1077 | .uleb128 0x18 1078 | .uleb128 0x2e 1079 | .byte 0x1 1080 | .uleb128 0x3f 1081 | .uleb128 0x19 1082 | .uleb128 0x3 1083 | .uleb128 0xe 1084 | .uleb128 0x3a 1085 | .uleb128 0xb 1086 | .uleb128 0x3b 1087 | .uleb128 0xb 1088 | .uleb128 0x39 1089 | .uleb128 0xb 1090 | .uleb128 0x27 1091 | .uleb128 0x19 1092 | .uleb128 0x49 1093 | .uleb128 0x13 1094 | .uleb128 0x20 1095 | .uleb128 0xb 1096 | .uleb128 0x1 1097 | .uleb128 0x13 1098 | .byte 0 1099 | .byte 0 1100 | .uleb128 0x19 1101 | .uleb128 0x5 1102 | .byte 0 1103 | .uleb128 0x3 1104 | .uleb128 0xe 1105 | .uleb128 0x3a 1106 | .uleb128 0xb 1107 | .uleb128 0x3b 1108 | .uleb128 0xb 1109 | .uleb128 0x39 1110 | .uleb128 0xb 1111 | .uleb128 0x49 1112 | .uleb128 0x13 1113 | .byte 0 1114 | .byte 0 1115 | .uleb128 0x1a 1116 | .uleb128 0x34 1117 | .byte 0 1118 | .uleb128 0x3 1119 | .uleb128 0x8 1120 | .uleb128 0x3a 1121 | .uleb128 0xb 1122 | .uleb128 0x3b 1123 | .uleb128 0xb 1124 | .uleb128 0x39 1125 | .uleb128 0xb 1126 | .uleb128 0x49 1127 | .uleb128 0x13 1128 | .byte 0 1129 | .byte 0 1130 | .uleb128 0x1b 1131 | .uleb128 0x2e 1132 | .byte 0x1 1133 | .uleb128 0x31 1134 | .uleb128 0x13 1135 | .uleb128 0x11 1136 | .uleb128 0x1 1137 | .uleb128 0x12 1138 | .uleb128 0x6 1139 | .uleb128 0x40 1140 | .uleb128 0x18 1141 | .uleb128 0x2117 1142 | .uleb128 0x19 1143 | .uleb128 0x1 1144 | .uleb128 0x13 1145 | .byte 0 1146 | .byte 0 1147 | .uleb128 0x1c 1148 | .uleb128 0x2e 1149 | .byte 0 1150 | .uleb128 0x3f 1151 | .uleb128 0x19 1152 | .uleb128 0x3c 1153 | .uleb128 0x19 1154 | .uleb128 0x6e 1155 | .uleb128 0xe 1156 | .uleb128 0x3 1157 | .uleb128 0xe 1158 | .uleb128 0x3a 1159 | .uleb128 0xb 1160 | .uleb128 0x3b 1161 | .uleb128 0x5 1162 | .uleb128 0x39 1163 | .uleb128 0xb 1164 | .byte 0 1165 | .byte 0 1166 | .byte 0 1167 | .section .debug_loc,"",%progbits 1168 | .Ldebug_loc0: 1169 | .LVUS3: 1170 | .uleb128 .LVU23 1171 | .uleb128 .LVU25 1172 | .uleb128 .LVU25 1173 | .uleb128 .LVU33 1174 | .uleb128 .LVU33 1175 | .uleb128 .LVU42 1176 | .LLST3: 1177 | .4byte .LVL4 1178 | .4byte .LVL5 1179 | .2byte 0x6 1180 | .byte 0x3 1181 | .4byte outStr 1182 | .byte 0x9f 1183 | .4byte .LVL5 1184 | .4byte .LVL7 1185 | .2byte 0x1 1186 | .byte 0x53 1187 | .4byte .LVL7 1188 | .4byte .LVL9 1189 | .2byte 0x3 1190 | .byte 0x73 1191 | .sleb128 1 1192 | .byte 0x9f 1193 | .4byte 0 1194 | .4byte 0 1195 | .LVUS4: 1196 | .uleb128 .LVU23 1197 | .uleb128 .LVU25 1198 | .uleb128 .LVU25 1199 | .uleb128 .LVU30 1200 | .uleb128 .LVU30 1201 | .uleb128 .LVU40 1202 | .uleb128 .LVU40 1203 | .uleb128 .LVU42 1204 | .LLST4: 1205 | .4byte .LVL4 1206 | .4byte .LVL5 1207 | .2byte 0x1 1208 | .byte 0x51 1209 | .4byte .LVL5 1210 | .4byte .LVL6 1211 | .2byte 0x1 1212 | .byte 0x52 1213 | .4byte .LVL6 1214 | .4byte .LVL8 1215 | .2byte 0x3 1216 | .byte 0x72 1217 | .sleb128 -1 1218 | .byte 0x9f 1219 | .4byte .LVL8 1220 | .4byte .LVL9 1221 | .2byte 0x3 1222 | .byte 0x72 1223 | .sleb128 1 1224 | .byte 0x9f 1225 | .4byte 0 1226 | .4byte 0 1227 | .LVUS5: 1228 | .uleb128 .LVU30 1229 | .uleb128 .LVU31 1230 | .uleb128 .LVU31 1231 | .uleb128 .LVU32 1232 | .uleb128 .LVU32 1233 | .uleb128 .LVU42 1234 | .LLST5: 1235 | .4byte .LVL6 1236 | .4byte .LVL6 1237 | .2byte 0x1 1238 | .byte 0x54 1239 | .4byte .LVL6 1240 | .4byte .LVL6 1241 | .2byte 0x3 1242 | .byte 0x74 1243 | .sleb128 -32 1244 | .byte 0x9f 1245 | .4byte .LVL6 1246 | .4byte .LVL9 1247 | .2byte 0x1 1248 | .byte 0x54 1249 | .4byte 0 1250 | .4byte 0 1251 | .LVUS0: 1252 | .uleb128 .LVU1 1253 | .uleb128 .LVU16 1254 | .uleb128 .LVU16 1255 | .uleb128 0 1256 | .LLST0: 1257 | .4byte .LVL0 1258 | .4byte .LVL3 1259 | .2byte 0x4 1260 | .byte 0xf3 1261 | .uleb128 0x1 1262 | .byte 0x50 1263 | .byte 0x9f 1264 | .4byte .LVL3 1265 | .4byte .LFE11 1266 | .2byte 0x6 1267 | .byte 0xf3 1268 | .uleb128 0x1 1269 | .byte 0x50 1270 | .byte 0x23 1271 | .uleb128 0x1 1272 | .byte 0x9f 1273 | .4byte 0 1274 | .4byte 0 1275 | .LVUS1: 1276 | .uleb128 .LVU1 1277 | .uleb128 .LVU9 1278 | .uleb128 .LVU9 1279 | .uleb128 0 1280 | .LLST1: 1281 | .4byte .LVL0 1282 | .4byte .LVL2 1283 | .2byte 0x4 1284 | .byte 0xf3 1285 | .uleb128 0x1 1286 | .byte 0x51 1287 | .byte 0x9f 1288 | .4byte .LVL2 1289 | .4byte .LFE11 1290 | .2byte 0x3 1291 | .byte 0x71 1292 | .sleb128 1 1293 | .byte 0x9f 1294 | .4byte 0 1295 | .4byte 0 1296 | .LVUS2: 1297 | .uleb128 .LVU6 1298 | .uleb128 .LVU7 1299 | .uleb128 .LVU7 1300 | .uleb128 .LVU8 1301 | .uleb128 .LVU8 1302 | .uleb128 0 1303 | .LLST2: 1304 | .4byte .LVL1 1305 | .4byte .LVL1 1306 | .2byte 0x1 1307 | .byte 0x53 1308 | .4byte .LVL1 1309 | .4byte .LVL1 1310 | .2byte 0x3 1311 | .byte 0x73 1312 | .sleb128 -32 1313 | .byte 0x9f 1314 | .4byte .LVL1 1315 | .4byte .LFE11 1316 | .2byte 0x1 1317 | .byte 0x53 1318 | .4byte 0 1319 | .4byte 0 1320 | .section .debug_aranges,"",%progbits 1321 | .4byte 0x24 1322 | .2byte 0x2 1323 | .4byte .Ldebug_info0 1324 | .byte 0x4 1325 | .byte 0 1326 | .2byte 0 1327 | .2byte 0 1328 | .4byte .Ltext0 1329 | .4byte .Letext0-.Ltext0 1330 | .4byte .LFB12 1331 | .4byte .LFE12-.LFB12 1332 | .4byte 0 1333 | .4byte 0 1334 | .section .debug_ranges,"",%progbits 1335 | .Ldebug_ranges0: 1336 | .4byte .LBB4 1337 | .4byte .LBE4 1338 | .4byte .LBB6 1339 | .4byte .LBE6 1340 | .4byte 0 1341 | .4byte 0 1342 | .4byte .Ltext0 1343 | .4byte .Letext0 1344 | .4byte .LFB12 1345 | .4byte .LFE12 1346 | .4byte 0 1347 | .4byte 0 1348 | .section .debug_line,"",%progbits 1349 | .Ldebug_line0: 1350 | .section .debug_str,"MS",%progbits,1 1351 | .LASF22: 1352 | .ascii "_IO_buf_end\000" 1353 | .LASF9: 1354 | .ascii "__quad_t\000" 1355 | .LASF30: 1356 | .ascii "_old_offset\000" 1357 | .LASF50: 1358 | .ascii "sys_nerr\000" 1359 | .LASF25: 1360 | .ascii "_IO_save_end\000" 1361 | .LASF5: 1362 | .ascii "short int\000" 1363 | .LASF8: 1364 | .ascii "size_t\000" 1365 | .LASF35: 1366 | .ascii "_offset\000" 1367 | .LASF19: 1368 | .ascii "_IO_write_ptr\000" 1369 | .LASF14: 1370 | .ascii "_flags\000" 1371 | .LASF21: 1372 | .ascii "_IO_buf_base\000" 1373 | .LASF26: 1374 | .ascii "_markers\000" 1375 | .LASF16: 1376 | .ascii "_IO_read_end\000" 1377 | .LASF39: 1378 | .ascii "_freeres_buf\000" 1379 | .LASF55: 1380 | .ascii "outstr\000" 1381 | .LASF62: 1382 | .ascii "mytoupper\000" 1383 | .LASF49: 1384 | .ascii "stderr\000" 1385 | .LASF6: 1386 | .ascii "long long int\000" 1387 | .LASF56: 1388 | .ascii "GNU C17 8.3.0 -mfloat-abi=hard -mfpu=vfp -mtls-dial" 1389 | .ascii "ect=gnu -marm -march=armv6+fp -g -O3\000" 1390 | .LASF52: 1391 | .ascii "tstStr\000" 1392 | .LASF34: 1393 | .ascii "_lock\000" 1394 | .LASF11: 1395 | .ascii "long int\000" 1396 | .LASF63: 1397 | .ascii "printf\000" 1398 | .LASF31: 1399 | .ascii "_cur_column\000" 1400 | .LASF59: 1401 | .ascii "_IO_FILE\000" 1402 | .LASF54: 1403 | .ascii "instr\000" 1404 | .LASF1: 1405 | .ascii "unsigned char\000" 1406 | .LASF4: 1407 | .ascii "signed char\000" 1408 | .LASF36: 1409 | .ascii "_codecvt\000" 1410 | .LASF7: 1411 | .ascii "long long unsigned int\000" 1412 | .LASF0: 1413 | .ascii "unsigned int\000" 1414 | .LASF44: 1415 | .ascii "_IO_marker\000" 1416 | .LASF33: 1417 | .ascii "_shortbuf\000" 1418 | .LASF58: 1419 | .ascii "/home/pi/asm/Chapter 14\000" 1420 | .LASF18: 1421 | .ascii "_IO_write_base\000" 1422 | .LASF42: 1423 | .ascii "_unused2\000" 1424 | .LASF15: 1425 | .ascii "_IO_read_ptr\000" 1426 | .LASF2: 1427 | .ascii "short unsigned int\000" 1428 | .LASF13: 1429 | .ascii "char\000" 1430 | .LASF61: 1431 | .ascii "main\000" 1432 | .LASF57: 1433 | .ascii "upper.c\000" 1434 | .LASF37: 1435 | .ascii "_wide_data\000" 1436 | .LASF38: 1437 | .ascii "_freeres_list\000" 1438 | .LASF40: 1439 | .ascii "__pad5\000" 1440 | .LASF45: 1441 | .ascii "_IO_codecvt\000" 1442 | .LASF3: 1443 | .ascii "long unsigned int\000" 1444 | .LASF20: 1445 | .ascii "_IO_write_end\000" 1446 | .LASF12: 1447 | .ascii "__off64_t\000" 1448 | .LASF10: 1449 | .ascii "__off_t\000" 1450 | .LASF27: 1451 | .ascii "_chain\000" 1452 | .LASF46: 1453 | .ascii "_IO_wide_data\000" 1454 | .LASF24: 1455 | .ascii "_IO_backup_base\000" 1456 | .LASF47: 1457 | .ascii "stdin\000" 1458 | .LASF29: 1459 | .ascii "_flags2\000" 1460 | .LASF41: 1461 | .ascii "_mode\000" 1462 | .LASF17: 1463 | .ascii "_IO_read_base\000" 1464 | .LASF32: 1465 | .ascii "_vtable_offset\000" 1466 | .LASF23: 1467 | .ascii "_IO_save_base\000" 1468 | .LASF51: 1469 | .ascii "sys_errlist\000" 1470 | .LASF28: 1471 | .ascii "_fileno\000" 1472 | .LASF43: 1473 | .ascii "FILE\000" 1474 | .LASF53: 1475 | .ascii "outStr\000" 1476 | .LASF48: 1477 | .ascii "stdout\000" 1478 | .LASF60: 1479 | .ascii "_IO_lock_t\000" 1480 | .ident "GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0" 1481 | .section .note.GNU-stack,"",%progbits 1482 | -------------------------------------------------------------------------------- /Source Code/Chapter 14/upper2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BUFFERSIZE 250 4 | 5 | char *tstStr = "This is a test!"; 6 | char outStr[BUFFERSIZE]; 7 | 8 | int main() 9 | { 10 | toupper(tstStr, outStr); 11 | printf("Input: %s\nOutput: %s\n", tstStr, outStr); 12 | 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 15. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .syntax unified 10 | 11 | .global _start 12 | 13 | @ ARM Code 14 | _start: 15 | l1: LDR R0, =myfunc 16 | BLX R0 17 | 18 | @ Setup the parameters to exit the program 19 | @ and then call Linux to do it. 20 | MOV R0, #0 @ Use 0 return code 21 | MOV R7, #1 @ Service command code 1 terminates this program 22 | SVC 0 @ Call linux to terminate the program 23 | 24 | .thumb_func 25 | myfunc: 26 | L2: ADDS R2, R1, #2 27 | ADDS R2, #153 28 | ADDS R2, R0, R1 29 | 30 | L3: IT EQ 31 | ADDEQ R2, R1 32 | 33 | L4: SUBS r3, #32 34 | UXTB r3, r3 35 | 36 | BX LR 37 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/main.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case by calling a function. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R1 - address of output string 7 | @ R0 - address of input string 8 | @ R5 - current character being processed 9 | @ R7 - linux function number 10 | @ 11 | 12 | .global _start @ Provide program starting address to linker 13 | 14 | _start: LDR R0, =instr @ start of input string 15 | LDR R1, =outstr @ address of output string 16 | MOV R4, #12 17 | MOV R5, #13 18 | 19 | BLX toupper 20 | 21 | @ Setup the parameters to print our hex number 22 | @ and then call Linux to do it. 23 | MOV R2,R0 @ return code is the length of the string 24 | 25 | MOV R0, #1 @ 1 = StdOut 26 | LDR R1, =outstr @ string to print 27 | MOV R7, #4 @ linux write system call 28 | SVC 0 @ Call linux to output the string 29 | 30 | @ Setup the parameters to exit the program 31 | @ and then call Linux to do it. 32 | MOV R0, #0 @ Use 0 return code 33 | MOV R7, #1 @ Service command code 1 terminates this program 34 | SVC 0 @ Call linux to terminate the program 35 | 36 | .data 37 | instr: .asciz "This is our Test String that we will convert. AaZz@[`{\n" 38 | .align 4 39 | outstr: .fill 255, 1, 0 40 | 41 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/makefile: -------------------------------------------------------------------------------- 1 | 2 | UPPER2OBJS = main.o upper2.o 3 | UPPER3OBJS = main.o upper3.o 4 | 5 | ifdef DEBUG 6 | DEBUGFLGS = -g 7 | else 8 | DEBUGFLGS = 9 | endif 10 | LSTFLGS = 11 | 12 | all: upper2 upper3 codesnippets 13 | 14 | %.o : %.s 15 | as -march="armv8-a" -mfpu=neon-vfpv4 $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 16 | 17 | upper2: $(UPPER2OBJS) 18 | ld -o upper2 $(UPPER2OBJS) 19 | 20 | upper3: $(UPPER3OBJS) 21 | ld -o upper3 $(UPPER3OBJS) 22 | 23 | codesnippets: codesnippets.o 24 | ld -o codesnippets codesnippets.o -------------------------------------------------------------------------------- /Source Code/Chapter 15/od2.txt: -------------------------------------------------------------------------------- 1 | 2 | upper2: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 00010074 <_start>: 8 | 10074: e59f002c ldr r0, [pc, #44] ; 100a8 <_start+0x34> 9 | 10078: e59f102c ldr r1, [pc, #44] ; 100ac <_start+0x38> 10 | 1007c: e3a0400c mov r4, #12 11 | 10080: e3a0500d mov r5, #13 12 | 10084: fa000009 blx 100b0 13 | 10088: e1a02000 mov r2, r0 14 | 1008c: e3a00001 mov r0, #1 15 | 10090: e59f1014 ldr r1, [pc, #20] ; 100ac <_start+0x38> 16 | 10094: e3a07004 mov r7, #4 17 | 10098: ef000000 svc 0x00000000 18 | 1009c: e3a00000 mov r0, #0 19 | 100a0: e3a07001 mov r7, #1 20 | 100a4: ef000000 svc 0x00000000 21 | 100a8: 000200e0 .word 0x000200e0 22 | 100ac: 00020120 .word 0x00020120 23 | 24 | 000100b0 : 25 | 100b0: b470 push {r4, r5, r6} 26 | 100b2: 460c mov r4, r1 27 | 28 | 000100b4 : 29 | 100b4: f810 5b01 ldrb.w r5, [r0], #1 30 | 100b8: f1a5 0661 sub.w r6, r5, #97 ; 0x61 31 | 100bc: 2e19 cmp r6, #25 32 | 100be: bf98 it ls 33 | 100c0: 3d20 subls r5, #32 34 | 100c2: f801 5b01 strb.w r5, [r1], #1 35 | 100c6: 2d00 cmp r5, #0 36 | 100c8: d1f4 bne.n 100b4 37 | 100ca: eba1 0004 sub.w r0, r1, r4 38 | 100ce: bc70 pop {r4, r5, r6} 39 | 100d0: 4770 bx lr 40 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/od3.txt: -------------------------------------------------------------------------------- 1 | 2 | upper3: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 00010074 <_start>: 8 | 10074: e59f002c ldr r0, [pc, #44] ; 100a8 <_start+0x34> 9 | 10078: e59f102c ldr r1, [pc, #44] ; 100ac <_start+0x38> 10 | 1007c: e3a0400c mov r4, #12 11 | 10080: e3a0500d mov r5, #13 12 | 10084: fa000009 blx 100b0 13 | 10088: e1a02000 mov r2, r0 14 | 1008c: e3a00001 mov r0, #1 15 | 10090: e59f1014 ldr r1, [pc, #20] ; 100ac <_start+0x38> 16 | 10094: e3a07004 mov r7, #4 17 | 10098: ef000000 svc 0x00000000 18 | 1009c: e3a00000 mov r0, #0 19 | 100a0: e3a07001 mov r7, #1 20 | 100a4: ef000000 svc 0x00000000 21 | 100a8: 000200d0 .word 0x000200d0 22 | 100ac: 00020110 .word 0x00020110 23 | 24 | 000100b0 : 25 | 100b0: b4f0 push {r4, r5, r6, r7} 26 | 100b2: 460c mov r4, r1 27 | 100b4: 2761 movs r7, #97 ; 0x61 28 | 29 | 000100b6 : 30 | 100b6: 7805 ldrb r5, [r0, #0] 31 | 100b8: 3001 adds r0, #1 32 | 100ba: 1bee subs r6, r5, r7 33 | 100bc: 2e19 cmp r6, #25 34 | 100be: bf98 it ls 35 | 100c0: 3d20 subls r5, #32 36 | 100c2: 700d strb r5, [r1, #0] 37 | 100c4: 3101 adds r1, #1 38 | 100c6: 2d00 cmp r5, #0 39 | 100c8: d1f5 bne.n 100b6 40 | 100ca: 1b08 subs r0, r1, r4 41 | 100cc: bcf0 pop {r4, r5, r6, r7} 42 | 100ce: 4770 bx lr 43 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/odcs.txt: -------------------------------------------------------------------------------- 1 | 2 | codesnippets: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 00010054 <_start>: 8 | 10054: e59f001c ldr r0, [pc, #28] ; 10078 9 | 10058: e12fff30 blx r0 10 | 1005c: e3a00000 mov r0, #0 11 | 10060: e3a07001 mov r7, #1 12 | 10064: ef000000 svc 0x00000000 13 | 14 | 00010068 : 15 | 10068: 1c8a adds r2, r1, #2 16 | 1006a: 3299 adds r2, #153 ; 0x99 17 | 1006c: 1842 adds r2, r0, r1 18 | 19 | 0001006e : 20 | 1006e: bf08 it eq 21 | 10070: 1852 addeq r2, r2, r1 22 | 23 | 00010072 : 24 | 10072: 3b20 subs r3, #32 25 | 10074: b2db uxtb r3, r3 26 | 10076: 4770 bx lr 27 | 10078: 00010069 .word 0x00010069 28 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/upper2.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ R6 - minus 'a' to compare < 26. 10 | @ 11 | 12 | .syntax unified 13 | 14 | .global toupper @ Allow other files to call this routine 15 | 16 | .thumb_func 17 | toupper: PUSH {R4-R6} @ Save the registers we use. 18 | MOV R4, R1 19 | @ The loop is until byte pointed to by R1 is non-zero 20 | loop: LDRB R5, [R0], #1 @ load character and increment pointer 21 | @ Want to know if 'a' <= R5 <= 'z' 22 | @ First subtract 'a' 23 | SUB R6, R5, #'a' 24 | @ Now want to know if R6 <= 25 25 | CMP R6, #25 @ chars are 0-25 after shift 26 | @ if we got here then the letter is lowercase, so convert it. 27 | IT LS 28 | SUBLS R5, #('a'-'A') 29 | STRB R5, [R1], #1 @ store character to output str 30 | CMP R5, #0 @ stop on hitting a null character 31 | BNE loop @ loop if character isn't null 32 | SUB R0, R1, R4 @ get the length by subtracting the pointers 33 | POP {R4-R6} @ Restore the register we use. 34 | BX LR @ Return to caller 35 | -------------------------------------------------------------------------------- /Source Code/Chapter 15/upper3.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ R6 - minus 'a' to compare < 26. 10 | @ 11 | 12 | .syntax unified 13 | 14 | .global toupper @ Allow other files to call this routine 15 | 16 | .thumb_func 17 | toupper: PUSH {R4-R7} @ Save the registers we use. 18 | MOV R4, R1 19 | MOVS R7, #'a' 20 | @ The loop is until byte pointed to by R1 is non-zero 21 | loop: LDRB R5, [R0] @ load character 22 | ADDS R0, #1 @ increment pointer 23 | @ Want to know if 'a' <= R5 <= 'z' 24 | @ First subtract 'a' 25 | SUBS R6, R5, R7 26 | @ Now want to know if R6 <= 25 27 | CMP R6, #25 @ chars are 0-25 after shift 28 | @ if we got here then the letter is lowercase, so convert it. 29 | IT LS 30 | SUBLS R5, #('a'-'A') 31 | 32 | STRB R5, [R1] @ store character to output str 33 | ADDS R1, #1 @ increment ouput pointer 34 | CMP R5, #0 @ stop on hitting a null character 35 | BNE loop @ loop if character isn't null 36 | SUBS R0, R1, R4 @ get the length by subtracting the pointers 37 | POP {R4-R7} @ Restore the register we use. 38 | BX LR @ Return to caller 39 | -------------------------------------------------------------------------------- /Source Code/Chapter 16/main.s: -------------------------------------------------------------------------------- 1 | // 2 | // Assembler program to convert a string to 3 | // all upper case by calling a function. 4 | // 5 | // X0-X2 - parameters to linux function services 6 | // X1 - address of output string 7 | // X0 - address of input string 8 | // X8 - linux function number 9 | // 10 | 11 | .global _start // Provide program starting address to linker 12 | 13 | _start: LDR X0, =instr // start of input string 14 | LDR X1, =outstr // address of output string 15 | 16 | BL toupper 17 | 18 | // Setup the parameters to print our hex number 19 | // and then call Linux to do it. 20 | MOV W2,W0 // return code is the length of the string 21 | 22 | MOV W0, #1 // 1 = StdOut 23 | LDR X1, =outstr // string to print 24 | MOV X8, #64 // linux write system call 25 | SVC 0 // Call linux to output the string 26 | 27 | // Setup the parameters to exit the program 28 | // and then call Linux to do it. 29 | MOV W0, #0 // Use 0 return code 30 | MOV X8, #93 // Service command code 93 terminates this program 31 | SVC 0 // Call linux to terminate the program 32 | 33 | .data 34 | instr: .asciz "This is our Test String that we will convert. AaZz@[`{\n" 35 | .align 4 36 | outstr: .fill 255, 1, 0 37 | .align 16 38 | -------------------------------------------------------------------------------- /Source Code/Chapter 16/makefile: -------------------------------------------------------------------------------- 1 | UPPEROBJS = main.o upper.o 2 | UPPER2OBJS = main.o upper2.o 3 | UPPER3OBJS = upper3.o 4 | UPPER4OBJS = main.o upper4.o 5 | 6 | ifdef DEBUG 7 | DEBUGFLGS = -g 8 | else 9 | DEBUGFLGS = 10 | endif 11 | LSTFLGS = 12 | 13 | all: upper upper2 upper3 upper4 14 | 15 | %.o : %.s 16 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 17 | 18 | upper: $(UPPEROBJS) 19 | ld -o upper $(UPPEROBJS) 20 | 21 | upper2: $(UPPER2OBJS) 22 | ld -o upper2 $(UPPER2OBJS) 23 | 24 | upper3: $(UPPER3OBJS) 25 | ld -o upper3 $(UPPER3OBJS) 26 | 27 | upper4: $(UPPER4OBJS) 28 | ld -o upper4 $(UPPER4OBJS) 29 | -------------------------------------------------------------------------------- /Source Code/Chapter 16/upper.s: -------------------------------------------------------------------------------- 1 | // 2 | // Assembler program to convert a string to 3 | // all upper case. 4 | // 5 | // X1 - address of output string 6 | // X0 - address of input string 7 | // X4 - original output string for length calc. 8 | // W5 - current character being processed 9 | // W6 - minus 'a' to compare < 26. 10 | // 11 | 12 | .global toupper // Allow other files to call this routine 13 | 14 | toupper: 15 | MOV X4, X1 16 | // The loop is until byte pointed to by R1 is non-zero 17 | loop: LDRB W5, [X0], #1 // load character and increment pointer 18 | // Want to know if 'a' <= R5 <= 'z' 19 | // First subtract 'a' 20 | SUB W6, W5, #'a' 21 | // Now want to know if R6 <= 25 22 | CMP W6, #25 // chars are 0-25 after shift 23 | BHI cont 24 | // if we got here then the letter is lowercase, so convert it. 25 | SUB W5, W5, #('a'-'A') 26 | cont: // end if 27 | STRB W5, [X1], #1 // store character to output str 28 | CMP W5, #0 // stop on hitting a null character 29 | BNE loop // loop if character isn't null 30 | SUB X0, X1, X4 // get the length by subtracting the pointers 31 | RET // Return to caller 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 16/upper2.s: -------------------------------------------------------------------------------- 1 | // 2 | // Assembler program to convert a string to 3 | // all upper case. 4 | // 5 | // X1 - address of output string 6 | // X0 - address of input string 7 | // X4 - original output string for length calc. 8 | // W5 - current character being processed 9 | // W6 - minus 'a' to compare < 26. 10 | // W6 - char minus 0x20, potentiall upper cased 11 | // 12 | 13 | .global toupper // Allow other files to call this routine 14 | 15 | toupper: 16 | MOV X4, X1 17 | // The loop is until byte pointed to by R1 is non-zero 18 | loop: LDRB W5, [X0], #1 // load character and increment pointer 19 | // Want to know if 'a' <= W5 <= 'z' 20 | // First subtract 'a' 21 | SUB W6, W5, #'a' 22 | // Now want to know if W6 <= 25 23 | CMP W6, #25 // chars are 0-25 after shift 24 | // perform lower case conversion to W6 25 | SUB W6, W5, #('a'-'A') 26 | // Use W6 if lower case, other wise use orginal character in W5 27 | CSEL W5, W6, W5, LS 28 | STRB W5, [X1], #1 // store character to output str 29 | CMP W5, #0 // stop on hitting a null character 30 | BNE loop // loop if character isn't null 31 | SUB X0, X1, X4 // get the length by subtracting the pointers 32 | RET // Return to caller 33 | -------------------------------------------------------------------------------- /Source Code/Chapter 16/upper3.s: -------------------------------------------------------------------------------- 1 | // 2 | // Assembler program to convert a string to 3 | // all upper case. Assumes only alphabetic 4 | // characters. Uses bit clear blindly without 5 | // checking if character is alphabetic or not. 6 | // 7 | // X0 - address of input string 8 | // X1 - address of output string 9 | // X2 - original output string for length calc. 10 | // W3 - current character being processed 11 | // 12 | 13 | .global _start // Provide program starting address 14 | 15 | .MACRO toupper inputstr, outputstr 16 | LDR X0, =\inputstr // start of input string 17 | LDR X1, =\outputstr // address of output string 18 | MOV X2, X1 19 | // The loop is until byte pointed to by R1 is non-zero 20 | loop: LDRB W3, [X0], #1 // load character and increment pointer 21 | BIC W3, W3, #0x20 // kill the bit that makes it lower case 22 | STRB W3, [X1], #1 // store character to output str 23 | CMP W3, #0 // stop on hitting a null charactser 24 | BNE loop // loop if character isn't null 25 | SUB X0, X1, X2 // get the length by subtracting the pointers 26 | .ENDM 27 | 28 | _start: 29 | toupper instr, outstr 30 | 31 | // Setup the parameters to print our hex number 32 | // and then call Linux to do it. 33 | MOV X2,X0 // return code is the length of the string 34 | 35 | MOV X0, #1 // 1 = StdOut 36 | LDR X1, =outstr // string to print 37 | MOV X8, #64 // linux write system call 38 | SVC 0 // Call linux to output the string 39 | 40 | // Setup the parameters to exit the program 41 | // and then call Linux to do it. 42 | MOV X0, #0 // Use 0 return code 43 | MOV X8, #93 // Service command code 96 terminates 44 | SVC 0 // Call linux to terminate the program 45 | 46 | .data 47 | instr: .asciz "ThisIsRatherALargeVariableNameAaZz//[`{\n" 48 | .align 4 49 | outstr: .fill 255, 1, 0 50 | -------------------------------------------------------------------------------- /Source Code/Chapter 16/upper4.s: -------------------------------------------------------------------------------- 1 | // 2 | // Assembler program to convert a string to 3 | // all upper case. 4 | // 5 | // X0 - address of input string 6 | // X1 - address of output string 7 | // X2 - use as indirection to load data 8 | // Q0 - 8 characters to be processed 9 | // Q1 - contains all a's for comparison 10 | // Q2 - result of comparison with 'a's 11 | // Q3 - all 25's for comp 12 | // Q8 - spaces for bic operation 13 | 14 | .global toupper // Allow other files to call this routine 15 | 16 | .EQU N, 4 17 | toupper: 18 | LDR X2, =aaas 19 | LDR Q1, [X2] // Load Q1 with all as 20 | LDR X2, =endch 21 | LDR Q3, [X2] // Load Q3 with all 25's 22 | LDR X2, =spaces 23 | LDR Q8, [X2] // Load Q8 with all spaces 24 | MOV W3, #N 25 | // The loop is until byte pointed to by R1 is non-zero 26 | loop: LDR Q0, [X0], #16 // load 16 characters and increment pointer 27 | SUB V2.16B, V0.16B, V1.16B // Subtract 'a's 28 | CMHI V2.16B, V2.16B, V3.16B // compare chars to 25's 29 | NOT V2.16B, V2.16B // no CMLO so need to not 30 | AND V2.16B, V2.16B, V8.16B // and result with spaces 31 | BIC V0.16B, V0.16B, V2.16B // kill the bit that makes it lowercase 32 | STR Q0, [X1], #16 // store character to output str 33 | SUBS W3, W3, #1 // decrement loop counter and set flags 34 | BNE loop // loop if character isn't null 35 | MOV X0, #(N*16) // get the length by subtracting the pointers 36 | RET // Return to caller 37 | 38 | .data 39 | aaas: .fill 16, 1, 'a' // 16 a's 40 | endch: .fill 16, 1, 25 // after shift, chars are 0-25 41 | spaces: .fill 16, 1, 0x20 // spaces for bic 42 | 43 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/addexamp1.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Examples of the ADD/ADC instructions. 4 | @ 5 | .global _start @ Provide program starting address to linker 6 | 7 | @ Multiply 2 by -1 by using MVN and then adding 1 8 | _start: MVN R0, #2 9 | ADD R0, #1 10 | 11 | @ Setup the parameters to exit the program 12 | @ and then call Linux to do it. 13 | @ R0 is the return code and will be what we 14 | @ calculated above. 15 | mov R7, #1 @ Service command code 1 terminates this program 16 | svc 0 @ Call linux to terminate the program 17 | 18 | 19 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/addexamp2.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Example of 64-Bit addition with the ADD/ADC instructions. 4 | @ 5 | .global _start @ Provide program starting address to linker 6 | 7 | @ Load the registers with some data 8 | @ First 64-bit number is 0x00000003FFFFFFFF 9 | _start: MOV R2, #0x00000003 10 | MOV R3, #0xFFFFFFFF @Assembler will change to MVN 11 | @ Second 64-bit number is 0x0000000500000001 12 | MOV R4, #0x00000005 13 | MOV R5, #0x00000001 14 | 15 | ADDS R1, R3, R5 @ Lower order word 16 | ADC R0, R2, R4 @ Higher order word 17 | 18 | @ Setup the parameters to exit the programc 19 | @ and then call Linux to do it. 20 | @ R0 is the return code and will be what we 21 | @ calculated above. 22 | mov R7, #1 @ Service command code 1 terminates this program 23 | svc 0 @ Call linux to terminate the program 24 | 25 | 26 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/addexamps.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Examples of the ADD/ADC instructions. 4 | @ 5 | .global _start @ Provide program starting address to linker 6 | 7 | @ Multiply 2 by -1 by using MVN and then adding 1 8 | _start: MVN R0, #2 9 | ADD R0, #1 10 | 11 | 12 | @ Setup the parameters to exit the program 13 | @ and then call Linux to do it. 14 | @ MOV R0, #0 @ Use 0 return code 15 | mov R7, #1 @ Service command code 1 terminates this program 16 | svc 0 @ Call linux to terminate the program 17 | 18 | 19 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/build: -------------------------------------------------------------------------------- 1 | as -o movexamps.o movexamps.s 2 | ld -o movexamps movexamps.o 3 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/buildadd: -------------------------------------------------------------------------------- 1 | as -o addexamp1.o addexamp1.s 2 | ld -o addexamp1 addexamp1.o 3 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/buildadd1: -------------------------------------------------------------------------------- 1 | as -o addexamp1.o addexamp1.s 2 | ld -o addexamp1 addexamp1.o 3 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/buildadd2: -------------------------------------------------------------------------------- 1 | as -o addexamp2.o addexamp2.s 2 | ld -o addexamp2 addexamp2.o 3 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 2. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .global _start 10 | 11 | _start: 12 | 13 | l1: MOV R2, #0x6E3A 14 | MOVT R2, #0x4F5D 15 | 16 | l2: MOV R1, R2, LSL #1 @ Logical shift left 17 | 18 | l3: MOV R1, R2, LSR #1 @ Logical shift right 19 | MOV R1, R2, ASR #1 @Arithmetic shift right 20 | MOV R1, R2, ROR #1 @ Rotate right 21 | MOV R1, R2, RRX @ Rotate extended right 22 | 23 | l4: LSL R1, R2, #1 @ Logical shift left 24 | LSR R1, R2, #1 @ Logical shift right 25 | ASR R1, R2, #1 @Arithmetic shift right 26 | ROR R1, R2, #1 @ Rotate right 27 | RRX R1, R2 @ Rotate extended right 28 | 29 | l5: MOV R1, #0xAB000000 @ Too big for #imm16 30 | @ Uncomment the next line if you want to see the 31 | @ Assembler error for a constant that can't be 32 | @ represented. 33 | @ MOV R1, #0xABCDEF11 @ Too big for #imm16 and can’t be represented. 34 | 35 | l6: ADD R1, #1 36 | 37 | l7: ADD R1, R1, #1 38 | 39 | l8: ADDS R0, #1 40 | 41 | l9: ADDS R1, R3, R5 @ Lower order word 42 | ADC R0, R2, R4 @ Higher order word 43 | 44 | 45 | @ Setup the parameters to exit the program 46 | @ and then call Linux to do it. 47 | MOV R0, #0 @ Use 0 return code 48 | MOV R7, #1 @ Service command code 1 terminates this program 49 | SVC 0 @ Call linux to terminate the program 50 | 51 | .data 52 | helloworld: .ascii "Hello World!" 53 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/makefile: -------------------------------------------------------------------------------- 1 | MEOBJS = movexamps.o 2 | AE1OBJS = addexamp1.o 3 | AE2OBJS = addexamp2.o 4 | CSOBJS = codesnippets.o 5 | 6 | ifdef DEBUG 7 | DEBUGFLGS = -g 8 | else 9 | DEBUGFLGS = 10 | endif 11 | 12 | %.o : %.s 13 | as $(DEBUGFLGS) $< -o $@ 14 | 15 | all: movexamps addexamp1 addexamp2 codesnippets 16 | 17 | movexamps: $(MEOBJS) 18 | ld -o movexamps $(MEOBJS) 19 | 20 | addexamp1: $(AE1OBJS) 21 | ld -o addexamp1 $(AE1OBJS) 22 | 23 | addexamp2: $(AE2OBJS) 24 | ld -o addexamp1 $(AE2OBJS) 25 | 26 | codesnippets: $(CSOBJS) 27 | ld -o codesnippets $(CSOBJS) -------------------------------------------------------------------------------- /Source Code/Chapter 2/movexamps.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Examples of the MOV instruction. 4 | @ 5 | .global _start @ Provide program starting address to linker 6 | 7 | @ Load R2 with 0x4F5D6E3A first using MOV and MOVT 8 | _start: MOV R2, #0x6E3A 9 | MOVT R2, #0x4F5D 10 | 11 | @ Just move R2 into R1 12 | MOV R1, R2 13 | 14 | @ Now lets see all the shift versions of MOV 15 | MOV R1, R2, LSL #1 @ Logical shift left 16 | MOV R1, R2, LSR #1 @ Logical shift right 17 | MOV R1, R2, ASR #1 @Arithmetic shift right 18 | MOV R1, R2, ROR #1 @ Rotate right 19 | MOV R1, R2, RRX @ Rotate extended right 20 | 21 | @ Repeat the above shifts using the Assembler mnemonics. 22 | 23 | LSL R1, R2, #1 @ Logical shift left 24 | LSR R1, R2, #1 @ Logical shift right 25 | ASR R1, R2, #1 @Arithmetic shift right 26 | ROR R1, R2, #1 @ Rotate right 27 | RRX R1, R2 @ Rotate extended right 28 | 29 | @ Example that works with 8 bit immediate and shift 30 | MOV R1, #0xAB000000 @ Too big for #imm16 31 | 32 | @ Example that can't be represented and results in an error 33 | @ Uncomment the instruction if you want to see the error 34 | @ MOV R1, #0xABCDEF11 @ Too big for #imm16 and can’t be represented. 35 | 36 | @ Example of MVN 37 | MVN R1, #45 38 | 39 | @ Example of a MOV that the Assembler will change to MVN 40 | MOV R1, #0xFFFFFFFE @ (-2) 41 | 42 | @ Setup the parameters to exit the program 43 | @ and then call Linux to do it. 44 | mov R0, #0 @ Use 0 return code 45 | mov R7, #1 @ Service command code 1 terminates this program 46 | svc 0 @ Call linux to terminate the program 47 | 48 | 49 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/objd.txt: -------------------------------------------------------------------------------- 1 | 2 | movexamps.o: file format elf32-littlearm 3 | 4 | Contents of section .text: 5 | 0000 3a2e06e3 5d2f44e3 0210a0e1 8210a0e1 :...]/D......... 6 | 0010 a210a0e1 c210a0e1 e210a0e1 6210a0e1 ............b... 7 | 0020 8210a0e1 a210a0e1 c210a0e1 e210a0e1 ................ 8 | 0030 6210a0e1 ab14a0e3 2d10e0e3 0110e0e3 b.......-....... 9 | 0040 0000a0e3 0170a0e3 000000ef .....p...... 10 | Contents of section .ARM.attributes: 11 | 0000 41130000 00616561 62690001 09000000 A....aeabi...... 12 | 0010 06080801 .... 13 | 14 | Disassembly of section .text: 15 | 16 | 00000000 <_start>: 17 | 0: e3062e3a movw r2, #28218 ; 0x6e3a 18 | 4: e3442f5d movt r2, #20317 ; 0x4f5d 19 | 8: e1a01002 mov r1, r2 20 | c: e1a01082 lsl r1, r2, #1 21 | 10: e1a010a2 lsr r1, r2, #1 22 | 14: e1a010c2 asr r1, r2, #1 23 | 18: e1a010e2 ror r1, r2, #1 24 | 1c: e1a01062 rrx r1, r2 25 | 20: e1a01082 lsl r1, r2, #1 26 | 24: e1a010a2 lsr r1, r2, #1 27 | 28: e1a010c2 asr r1, r2, #1 28 | 2c: e1a010e2 ror r1, r2, #1 29 | 30: e1a01062 rrx r1, r2 30 | 34: e3a014ab mov r1, #-1426063360 ; 0xab000000 31 | 38: e3e0102d mvn r1, #45 ; 0x2d 32 | 3c: e3e01001 mvn r1, #1 33 | 40: e3a00000 mov r0, #0 34 | 44: e3a07001 mov r7, #1 35 | 48: ef000000 svc 0x00000000 36 | -------------------------------------------------------------------------------- /Source Code/Chapter 2/objdump.txt: -------------------------------------------------------------------------------- 1 | 2 | movexamps.o: file format elf32-littlearm 3 | 4 | Contents of section .text: 5 | 0000 3a2e06e3 5d2f44e3 0210a0e1 8210a0e1 :...]/D......... 6 | 0010 a210a0e1 c210a0e1 e210a0e1 6210a0e1 ............b... 7 | 0020 8210a0e1 a210a0e1 c210a0e1 e210a0e1 ................ 8 | 0030 6210a0e1 ab14a0e3 2d10e0e3 0110e0e3 b.......-....... 9 | 0040 0000a0e3 0170a0e3 000000ef .....p...... 10 | Contents of section .ARM.attributes: 11 | 0000 41130000 00616561 62690001 09000000 A....aeabi...... 12 | 0010 06080801 .... 13 | 14 | Disassembly of section .text: 15 | 16 | 00000000 <_start>: 17 | 0: e3062e3a movw r2, #28218 ; 0x6e3a 18 | 4: e3442f5d movt r2, #20317 ; 0x4f5d 19 | 8: e1a01002 mov r1, r2 20 | c: e1a01082 lsl r1, r2, #1 21 | 10: e1a010a2 lsr r1, r2, #1 22 | 14: e1a010c2 asr r1, r2, #1 23 | 18: e1a010e2 ror r1, r2, #1 24 | 1c: e1a01062 rrx r1, r2 25 | 20: e1a01082 lsl r1, r2, #1 26 | 24: e1a010a2 lsr r1, r2, #1 27 | 28: e1a010c2 asr r1, r2, #1 28 | 2c: e1a010e2 ror r1, r2, #1 29 | 30: e1a01062 rrx r1, r2 30 | 34: e3a014ab mov r1, #-1426063360 ; 0xab000000 31 | 38: e3e0102d mvn r1, #45 ; 0x2d 32 | 3c: e3e01001 mvn r1, #1 33 | 40: e3a00000 mov r0, #0 34 | 44: e3a07001 mov r7, #1 35 | 48: ef000000 svc 0x00000000 36 | -------------------------------------------------------------------------------- /Source Code/Chapter 4/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 4. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .global _start 10 | 11 | _start: 12 | @ uncomment the next 2 lines if you want to see 13 | @ an infinite loop 14 | l1: @ MOV R1, #1 15 | @B _start 16 | 17 | l2: CMP R4, #45 18 | BEQ _start 19 | 20 | l3: MOV R2, #1 @ R2 holds I 21 | loop: @ body of the loop goes here. 22 | @ Most of the logic is at the end 23 | ADD R2, #1 @ I = I + 1 24 | CMP R2, #10 25 | BLE loop @ IF I <= 10 goto loop 26 | 27 | l4: MOV R2, #10 @R2 holds I 28 | loop2: @ body of the loop goes here. 29 | @ The CMP is redundant since we 30 | @ are doing SUBS. 31 | SUBS R2, #1 @ I = I -1 32 | BNE loop2 @ branch until I = 0 33 | 34 | l5: @ R4 is X and has been initialized 35 | MOV R4, #5 36 | loop3: CMP R4, #5 37 | BGE loopdone 38 | @ … other statements in the loop body … 39 | MOV r4, #6 40 | B loop3 41 | loopdone: @program continues 42 | 43 | l6: CMP R5, #10 44 | BGE elseclause 45 | @ … if statements … 46 | B endif 47 | elseclause: 48 | @ … else statements … 49 | endif: @ continue on after the /then/else … 50 | 51 | l7: @ mask off the high order byte 52 | AND R6, #0xFF000000 53 | @ shift the byte down to the 54 | @ low order position. 55 | LSR R6, #24 56 | 57 | l8: ORR R6, #0xFF 58 | 59 | l9: BIC R6, #0xFF 60 | 61 | @ Setup the parameters to exit the program 62 | @ and then call Linux to do it. 63 | MOV R0, #0 @ Use 0 return code 64 | MOV R7, #1 @ Service command code 1 terminates this program 65 | SVC 0 @ Call linux to terminate the program 66 | 67 | .data 68 | helloworld: .ascii "Hello World!" 69 | -------------------------------------------------------------------------------- /Source Code/Chapter 4/makefile: -------------------------------------------------------------------------------- 1 | OBJS = printword.o 2 | CSOBJS = codesnippets.o 3 | 4 | ifdef DEBUG 5 | DEBUGFLGS = -g 6 | else 7 | DEBUGFLGS = 8 | endif 9 | 10 | %.o : %.s 11 | as $(DEBUGFLGS) $< -o $@ 12 | 13 | all: printword codesnippets 14 | 15 | printword: $(OBJS) 16 | ld -o printword $(OBJS) 17 | 18 | codesnippets: $(CSOBJS) 19 | ld -o codesnippets $(CSOBJS) -------------------------------------------------------------------------------- /Source Code/Chapter 4/printword.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to print a register in hex 3 | @ to stdout. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R1 - is also address of byte we are writing 7 | @ R4 - register to print 8 | @ R5 - loop index 9 | @ R6 - current character 10 | @ R7 - linux function number 11 | @ 12 | 13 | .global _start @ Provide program starting address to linker 14 | 15 | _start: MOV R4, #0x12AB @ number to print 16 | MOVT R4, #0xDE65 @ high bits of number to print 17 | LDR R1, =hexstr @ start of string 18 | ADD R1, #9 @ start at least sig digit 19 | @ The loop is FOR r5 = 8 TO 1 STEP -1 20 | MOV R5, #8 @ 8 digits to print 21 | loop: AND R6, r4, #0xf @ mask of least sig digit 22 | @ If R6 >= 10 then goto letter 23 | CMP R6, #10 @ is 0-9 or A-F 24 | BGE letter 25 | @ Else its a number so convert to an ASCII digit 26 | ADD R6, #'0' 27 | B cont @ goto to end if 28 | letter: @ handle the digits A to F 29 | ADD R6, #('A'-10) 30 | cont: @ end if 31 | STRB R6, [R1] @ store ascii digit 32 | SUB R1, #1 @ decrement address for next digit 33 | LSR R4, #4 @ shift off the digit we just processed 34 | 35 | @ next R5 36 | SUBS R5, #1 @ step R5 by -2 37 | BNE loop @ another for loop if not done 38 | 39 | @ Setup the parameters to print our hex number 40 | @ and then call Linux to do it. 41 | mov R0, #1 @ 1 = StdOut 42 | ldr R1, =hexstr @ string to print 43 | mov R2, #11 @ length of our string 44 | mov R7, #4 @ linux write system call 45 | svc 0 @ Call linux to output the string 46 | 47 | @ Setup the parameters to exit the program 48 | @ and then call Linux to do it. 49 | mov R0, #0 @ Use 0 return code 50 | mov R7, #1 @ Service command code 1 terminates this program 51 | svc 0 @ Call linux to terminate the program 52 | 53 | .data 54 | hexstr: .ascii "0x12345678\n" 55 | 56 | -------------------------------------------------------------------------------- /Source Code/Chapter 5/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 5. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .global _start 10 | 11 | .data 12 | l1: .byte 74, 0112, 0b00101010, 0x4A, 0X4a, 'J', 'H' + 2 13 | .word 0x1234ABCD, -1434 14 | .ascii "Hello World\n" 15 | 16 | l2: .byte -0x45, -33, ~0b00111001 17 | 18 | l3: .fill 10, 4, 0 19 | 20 | l4: .rept 3 21 | .byte 0, 1, 2 22 | .endr 23 | 24 | .text 25 | 26 | _start: 27 | l5: LDR R1, =helloworld 28 | 29 | l6: LDR R1, =0x1234ABCDF 30 | 31 | l7: 32 | @ load the address of mynumber into R1 33 | LDR R1, =mynumber 34 | @ load the word stored at mynumber into R2 35 | LDR R2, [R1] 36 | 37 | l8: LDR R1, =arr1 38 | 39 | l9: @ Load the first element 40 | LDR R2, [R1] 41 | @ Load element 3 42 | @ The elements count from 0, so 2 is 43 | @ the third one. Each word is 4 bytes, 44 | @ so we need to multiply by 4 45 | LDR R2, [R1, #(2 * 4)] 46 | 47 | l10: @ The 3rd element is still number 2 48 | MOV R3, #(2 * 4) 49 | @ Add the offset in R3 to R1 to get our element. 50 | LDR R2, [R1, R3] 51 | 52 | l11: LDR R2, [R1, #-(2 * 4)] 53 | LDR R2, [R1, -R3] 54 | 55 | l12: @ Suppose our array is of WORDs but we only want the 56 | @ low order byte. 57 | MOV R3, #2 58 | @ Shift R3 left by 2 positions to multiply 59 | @ by 4 to get the correct address. 60 | LDR R2, [R1, R3, LSL #2] 61 | 62 | l13: LDR R2, [R1, R3, LSL #2]! 63 | 64 | LDR R2, =arr1 65 | l14: @ Load R1 with the memory pointed to by R2 66 | @ Then do R2 = R2 + R3 67 | LDR R1, [R2], R3 68 | @ Load R1 with the memory pointed to by R2 69 | @ Then do R2 = R2 + 2 70 | LDR R1, [R2], #2 71 | @ Load R1 with the memory pointed to by R2 72 | @ Then do R2 = R2 + (R3 shifted 2 left) 73 | LDR R1, [R2], R3, LSL #2 74 | 75 | l15: LDR R1, =mydword 76 | LDRD R2, R3, [R1] 77 | STRD R2, R3, [R1] 78 | 79 | @ Setup the parameters to exit the program 80 | @ and then call Linux to do it. 81 | MOV R0, #0 @ Use 0 return code 82 | MOV R7, #1 @ Service command code 1 terminates this program 83 | SVC 0 @ Call linux to terminate the program 84 | 85 | .data 86 | helloworld: .ascii "Hello World!" 87 | mynumber: .WORD 0x1234ABCD 88 | arr1: .FILL 10, 4, 0 89 | @ As of this writing there is a bug in AS that causes the next 90 | @ statement to spit out a warning. You can disregard this 91 | @ and check with objdump that the generated data is correct. 92 | mydword: .QUAD 0x1234567887654321 93 | -------------------------------------------------------------------------------- /Source Code/Chapter 5/makefile: -------------------------------------------------------------------------------- 1 | CSOBJS = codesnippets.o 2 | UPPEROBJS = upper.o 3 | 4 | ifdef DEBUG 5 | DEBUGFLGS = -g 6 | else 7 | DEBUGFLGS = 8 | endif 9 | LSTFLGS = 10 | 11 | all: codesnippets upper 12 | 13 | %.o : %.s 14 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 15 | codesnippets: $(CSOBJS) 16 | ld -o codesnippets $(CSOBJS) 17 | 18 | upper: $(UPPEROBJS) 19 | ld -o upper $(UPPEROBJS) 20 | -------------------------------------------------------------------------------- /Source Code/Chapter 5/od.txt: -------------------------------------------------------------------------------- 1 | 2 | upper: file format elf32-littlearm 3 | 4 | SYMBOL TABLE: 5 | 00010074 l d .text 00000000 .text 6 | 000200c8 l d .data 00000000 .data 7 | 00000000 l d .ARM.attributes 00000000 .ARM.attributes 8 | 00000000 l d .debug_aranges 00000000 .debug_aranges 9 | 00000000 l d .debug_info 00000000 .debug_info 10 | 00000000 l d .debug_abbrev 00000000 .debug_abbrev 11 | 00000000 l d .debug_line 00000000 .debug_line 12 | 00000000 l d .debug_str 00000000 .debug_str 13 | 00000000 l df *ABS* 00000000 upper.o 14 | 000200c8 l .data 00000000 instr 15 | 000200f7 l .data 00000000 outstr 16 | 0001007c l .text 00000000 loop 17 | 00010094 l .text 00000000 cont 18 | 000201f6 g .data 00000000 _bss_end__ 19 | 000201f6 g .data 00000000 __bss_start__ 20 | 000201f6 g .data 00000000 __bss_end__ 21 | 00010074 g .text 00000000 _start 22 | 000201f6 g .data 00000000 __bss_start 23 | 000201f8 g .data 00000000 __end__ 24 | 000201f6 g .data 00000000 _edata 25 | 000201f8 g .data 00000000 _end 26 | 27 | 28 | Contents of section .text: 29 | 10074 44409fe5 44309fe5 0150d4e4 7a0055e3 D@..D0...P..z.U. 30 | 10084 020000ca 610055e3 000000ba 205045e2 ....a.U..... PE. 31 | 10094 0150c3e4 000055e3 f6ffff1a 0100a0e3 .P....U......... 32 | 100a4 18109fe5 012043e0 0470a0e3 000000ef ..... C..p...... 33 | 100b4 0000a0e3 0170a0e3 000000ef c8000200 .....p.......... 34 | 100c4 f7000200 .... 35 | Contents of section .data: 36 | 200c8 54686973 20697320 6f757220 54657374 This is our Test 37 | 200d8 20537472 696e6720 74686174 20776520 String that we 38 | 200e8 77696c6c 20636f6e 76657274 2e0a0000 will convert.... 39 | 200f8 00000000 00000000 00000000 00000000 ................ 40 | 20108 00000000 00000000 00000000 00000000 ................ 41 | 20118 00000000 00000000 00000000 00000000 ................ 42 | 20128 00000000 00000000 00000000 00000000 ................ 43 | 20138 00000000 00000000 00000000 00000000 ................ 44 | 20148 00000000 00000000 00000000 00000000 ................ 45 | 20158 00000000 00000000 00000000 00000000 ................ 46 | 20168 00000000 00000000 00000000 00000000 ................ 47 | 20178 00000000 00000000 00000000 00000000 ................ 48 | 20188 00000000 00000000 00000000 00000000 ................ 49 | 20198 00000000 00000000 00000000 00000000 ................ 50 | 201a8 00000000 00000000 00000000 00000000 ................ 51 | 201b8 00000000 00000000 00000000 00000000 ................ 52 | 201c8 00000000 00000000 00000000 00000000 ................ 53 | 201d8 00000000 00000000 00000000 00000000 ................ 54 | 201e8 00000000 00000000 00000000 0000 .............. 55 | Contents of section .ARM.attributes: 56 | 0000 41110000 00616561 62690001 07000000 A....aeabi...... 57 | 0010 0801 .. 58 | Contents of section .debug_aranges: 59 | 0000 1c000000 02000000 00000400 00000000 ................ 60 | 0010 74000100 54000000 00000000 00000000 t...T........... 61 | Contents of section .debug_info: 62 | 0000 22000000 02000000 00000401 00000000 "............... 63 | 0010 74000100 c8000100 00000000 08000000 t............... 64 | 0020 1f000000 0180 ...... 65 | Contents of section .debug_abbrev: 66 | 0000 01110010 06110112 01030e1b 0e250e13 .............%.. 67 | 0010 05000000 .... 68 | Contents of section .debug_line: 69 | 0000 49000000 02001e00 00000201 fb0e0d00 I............... 70 | 0010 01010101 00000001 00000100 75707065 ............uppe 71 | 0020 722e7300 00000000 00050274 00010003 r.s........t.... 72 | 0030 0d012f30 302f302f 30302f2f 322f2f2f ../00/0/00//2/// 73 | 0040 2f322f2f 03632e2f 02020001 01 /2//.c./..... 74 | Contents of section .debug_str: 75 | 0000 75707065 722e7300 2f686f6d 652f7069 upper.s./home/pi 76 | 0010 2f61736d 2f436861 70746572 20350047 /asm/Chapter 5.G 77 | 0020 4e552041 5320322e 33312e31 00 NU AS 2.31.1. 78 | 79 | Disassembly of section .text: 80 | 81 | 00010074 <_start>: 82 | 10074: e59f4044 ldr r4, [pc, #68] ; 100c0 83 | 10078: e59f3044 ldr r3, [pc, #68] ; 100c4 84 | 85 | 0001007c : 86 | 1007c: e4d45001 ldrb r5, [r4], #1 87 | 10080: e355007a cmp r5, #122 ; 0x7a 88 | 10084: ca000002 bgt 10094 89 | 10088: e3550061 cmp r5, #97 ; 0x61 90 | 1008c: ba000000 blt 10094 91 | 10090: e2455020 sub r5, r5, #32 92 | 93 | 00010094 : 94 | 10094: e4c35001 strb r5, [r3], #1 95 | 10098: e3550000 cmp r5, #0 96 | 1009c: 1afffff6 bne 1007c 97 | 100a0: e3a00001 mov r0, #1 98 | 100a4: e59f1018 ldr r1, [pc, #24] ; 100c4 99 | 100a8: e0432001 sub r2, r3, r1 100 | 100ac: e3a07004 mov r7, #4 101 | 100b0: ef000000 svc 0x00000000 102 | 100b4: e3a00000 mov r0, #0 103 | 100b8: e3a07001 mov r7, #1 104 | 100bc: ef000000 svc 0x00000000 105 | 100c0: 000200c8 .word 0x000200c8 106 | 100c4: 000200f7 .word 0x000200f7 107 | -------------------------------------------------------------------------------- /Source Code/Chapter 5/upper.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R3 - address of output string 7 | @ R4 - address of input string 8 | @ R5 - current character being processed 9 | @ R7 - linux function number 10 | @ 11 | 12 | .global _start @ Provide program starting address to linker 13 | 14 | _start: LDR R4, =instr @ start of input string 15 | LDR R3, =outstr @ address of output string 16 | @ The loop is until byte pointed to by R1 is non-zero 17 | loop: LDRB R5, [R4], #1 @ load character and increment pointer 18 | @ If R5 > 'z' then goto cont 19 | CMP R5, #'z' @ is letter > 'z'? 20 | BGT cont 21 | @ Else if R5 < 'a' then goto end if 22 | CMP R5, #'a' 23 | BLT cont @ goto to end if 24 | @ if we got here then the letter is lower case, so convert it. 25 | SUB R5, #('a'-'A') 26 | cont: @ end if 27 | STRB R5, [R3], #1 @ store character to output str 28 | CMP R5, #0 @ stop on hitting a null character 29 | BNE loop @ loop if character isn't null 30 | 31 | @ Setup the parameters to print our hex number 32 | @ and then call Linux to do it. 33 | MOV R0, #1 @ 1 = StdOut 34 | LDR R1, =outstr @ string to print 35 | SUB R2, R3, R1 @ get the length by subtracting the pointers 36 | MOV R7, #4 @ linux write system call 37 | SVC 0 @ Call linux to output the string 38 | 39 | @ Setup the parameters to exit the program 40 | @ and then call Linux to do it. 41 | MOV R0, #0 @ Use 0 return code 42 | MOV R7, #1 @ Service command code 1 terminates this program 43 | SVC 0 @ Call linux to terminate the program 44 | 45 | .data 46 | instr: .asciz "This is our Test String that we will convert.\n" 47 | outstr: .fill 255, 1, 0 48 | 49 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 6. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .global _start 10 | 11 | _start: 12 | l1: PUSH {r0, r5-r12} 13 | POP {r0, r5-r12} 14 | PUSH {r0-r4, r6, r9-r12} 15 | POP {r0-r4, r6, r9-r12} 16 | 17 | l2: BL myfunc 18 | MOV R1, #4 19 | B l3 20 | 21 | myfunc: @ do some work 22 | BX LR 23 | 24 | l3: BL myfuncb 25 | MOV R1, #4 26 | B l4 27 | 28 | myfuncb:PUSH {LR} 29 | @ do some work … 30 | BL myfuncb2 31 | @ do some more work... 32 | POP {LR} 33 | BX LR 34 | 35 | myfuncb2: @ do some work .... 36 | BX LR 37 | 38 | l4: SUB SP, #12 39 | 40 | l5: STR R0, [SP] @ Store a 41 | STR R1, [SP, #4] @ Store b 42 | STR R2, [SP, #8] @ Store c 43 | 44 | l6: ADD SP, #12 45 | 46 | l7: SUB FP, SP, #4 47 | SUB SP, #12 48 | 49 | l8: STR R0, [FP] @ Store a 50 | STR R1, [FP, #-4] @ Store b 51 | STR R2, [FP, #-8] @ Store c 52 | ADD SP, #12 53 | 54 | l9: BL SUMFN 55 | B l10 56 | 57 | @ Simple function that takes 2 parameters 58 | @ VAR1 and VAR2. The function adds them, 59 | @ storing the result in a variable SUM. 60 | @ The function returns the sum. 61 | @ It is assumed this function does other work, 62 | @ including other functions. 63 | 64 | @ Define our variables 65 | .EQU VAR1, 0 66 | .EQU VAR2, 4 67 | .EQU SUM, 8 68 | 69 | SUMFN: PUSH {R4-R12, LR} 70 | SUB SP, #12 @ room for three 32-bit values 71 | STR R0, [SP, #VAR1] @ save passed in param. 72 | STR R1, [SP, #VAR2] @ save second param. 73 | 74 | @ Do bunch of other work, but don’t change SP. 75 | 76 | LDR R4, [SP, #VAR1] 77 | LDR R5, [SP, #VAR2] 78 | ADD R6, R4, R5 79 | STR R6, [SP, #SUM] 80 | 81 | @ Do other work 82 | 83 | @ Function Epilog 84 | LDR R0, [SP, #SUM] @ load sum to return 85 | ADD SP, #12 @ Release local vars 86 | POP {R4-R12, PC} @ Restore regs and return 87 | 88 | l10: 89 | 90 | @ Setup the parameters to exit the program 91 | @ and then call Linux to do it. 92 | MOV R0, #0 @ Use 0 return code 93 | MOV R7, #1 @ Service command code 1 terminates this program 94 | SVC 0 @ Call linux to terminate the program 95 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/gdb.txt: -------------------------------------------------------------------------------- 1 | before bl toupper 2 | 3 | (gdb) i r 4 | r0 0x200e8 131304 5 | r1 0x20117 131351 6 | r2 0x0 0 7 | r3 0x0 0 8 | r4 0xc 12 9 | r5 0xd 13 10 | r6 0x0 0 11 | r7 0x0 0 12 | r8 0x0 0 13 | r9 0x0 0 14 | r10 0x0 0 15 | r11 0x0 0 16 | r12 0x0 0 17 | sp 0x7efff380 0x7efff380 18 | lr 0x0 0 19 | pc 0x10084 0x10084 <_start+16> 20 | cpsr 0x10 16 21 | fpscr 0x0 0 22 | 23 | after bl toupper 24 | 25 | (gdb) i r 26 | r0 0x200e8 131304 27 | r1 0x20117 131351 28 | r2 0x0 0 29 | r3 0x0 0 30 | r4 0xc 12 31 | r5 0xd 13 32 | r6 0x0 0 33 | r7 0x0 0 34 | r8 0x0 0 35 | r9 0x0 0 36 | r10 0x0 0 37 | r11 0x0 0 38 | r12 0x0 0 39 | sp 0x7efff380 0x7efff380 40 | lr 0x10088 65672 41 | pc 0x100b0 0x100b0 42 | cpsr 0x10 16 43 | fpscr 0x0 0 44 | 45 | after push r4-r5 46 | (gdb) i r 47 | r0 0x200e8 131304 48 | r1 0x20117 131351 49 | r2 0x0 0 50 | r3 0x0 0 51 | r4 0xc 12 52 | r5 0xd 13 53 | r6 0x0 0 54 | r7 0x0 0 55 | r8 0x0 0 56 | r9 0x0 0 57 | r10 0x0 0 58 | r11 0x0 0 59 | r12 0x0 0 60 | sp 0x7efff378 0x7efff378 61 | lr 0x10088 65672 62 | pc 0x100b4 0x100b4 63 | cpsr 0x10 16 64 | fpscr 0x0 0 65 | 66 | stack: 67 | (gdb) x /4xw 0x7efff378 68 | 0x7efff378: 0x0000000c 0x0000000d 0x00000001 0x7efff504 69 | 70 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/main.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case by calling a function. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R1 - address of output string 7 | @ R0 - address of input string 8 | @ R5 - current character being processed 9 | @ R7 - linux function number 10 | @ 11 | 12 | .global _start @ Provide program starting address to linker 13 | 14 | _start: LDR R0, =instr @ start of input string 15 | LDR R1, =outstr @ address of output string 16 | MOV R4, #12 17 | MOV R5, #13 18 | 19 | BL toupper 20 | 21 | @ Setup the parameters to print our hex number 22 | @ and then call Linux to do it. 23 | MOV R2,R0 @ return code is the length of the string 24 | 25 | MOV R0, #1 @ 1 = StdOut 26 | LDR R1, =outstr @ string to print 27 | MOV R7, #4 @ linux write system call 28 | SVC 0 @ Call linux to output the string 29 | 30 | @ Setup the parameters to exit the program 31 | @ and then call Linux to do it. 32 | MOV R0, #0 @ Use 0 return code 33 | MOV R7, #1 @ Service command code 1 terminates this program 34 | SVC 0 @ Call linux to terminate the program 35 | 36 | .data 37 | instr: .asciz "This is our Test String that we will convert.\n" 38 | outstr: .fill 255, 1, 0 39 | 40 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/mainmacro.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case by calling a function. 4 | @ 5 | @ R0-R2 - parameters to linux function services 6 | @ R1 - address of output string 7 | @ R0 - address of input string 8 | @ R5 - current character being processed 9 | @ R7 - linux function number 10 | @ 11 | 12 | .include "uppermacro.s" 13 | 14 | .global _start @ Provide program starting address to linker 15 | 16 | _start: toupper tststr, buffer 17 | 18 | @ Setup the parameters to print our hex number 19 | @ and then call Linux to do it. 20 | MOV R2,R0 @ return code is the length of the string 21 | 22 | MOV R0, #1 @ 1 = StdOut 23 | LDR R1, =buffer @ string to print 24 | MOV R7, #4 @ linux write system call 25 | SVC 0 @ Call linux to output the string 26 | 27 | toupper tststr2, buffer 28 | 29 | @ Setup the parameters to print our hex number 30 | @ and then call Linux to do it. 31 | MOV R2,R0 @ return code is the length of the string 32 | 33 | MOV R0, #1 @ 1 = StdOut 34 | LDR R1, =buffer @ string to print 35 | MOV R7, #4 @ linux write system call 36 | SVC 0 @ Call linux to output the string 37 | 38 | @ Setup the parameters to exit the program 39 | @ and then call Linux to do it. 40 | MOV R0, #0 @ Use 0 return code 41 | MOV R7, #1 @ Service command code 1 terminates this program 42 | SVC 0 @ Call linux to terminate the program 43 | 44 | .data 45 | tststr: .asciz "This is our Test String that we will convert.\n" 46 | tststr2: .asciz "A second string to upper case!!\n" 47 | buffer: .fill 255, 1, 0 48 | 49 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/makefile: -------------------------------------------------------------------------------- 1 | CSOBJS = codesnippets.o 2 | UPPEROBJS = main.o upper.o 3 | UPPERMACOBJS = mainmacro.o 4 | 5 | ifdef DEBUG 6 | DEBUGFLGS = -g 7 | else 8 | DEBUGFLGS = 9 | endif 10 | LSTFLGS = 11 | 12 | all: codesnippets upper uppermacro 13 | 14 | %.o : %.s 15 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 16 | codesnippets: $(CSOBJS) 17 | ld -o codesnippets $(CSOBJS) 18 | 19 | upper: $(UPPEROBJS) 20 | ld -o upper $(UPPEROBJS) 21 | 22 | uppermacro: $(UPPERMACOBJS) 23 | ld -o uppermacro $(UPPERMACOBJS) 24 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/ob.txt: -------------------------------------------------------------------------------- 1 | 2 | upper: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 00010074 <_start>: 8 | 10074: e59f0024 ldr r0, [pc, #36] ; 100a0 <_start+0x2c> 9 | 10078: e59f1024 ldr r1, [pc, #36] ; 100a4 <_start+0x30> 10 | 1007c: eb000009 bl 100a8 11 | 10080: e1a02000 mov r2, r0 12 | 10084: e3a00001 mov r0, #1 13 | 10088: e59f1014 ldr r1, [pc, #20] ; 100a4 <_start+0x30> 14 | 1008c: e3a07004 mov r7, #4 15 | 10090: ef000000 svc 0x00000000 16 | 10094: e3a00000 mov r0, #0 17 | 10098: e3a07001 mov r7, #1 18 | 1009c: ef000000 svc 0x00000000 19 | 100a0: 000200e0 .word 0x000200e0 20 | 100a4: 0002010f .word 0x0002010f 21 | 22 | 000100a8 : 23 | 100a8: e92d0030 push {r4, r5} 24 | 100ac: e1a04001 mov r4, r1 25 | 26 | 000100b0 : 27 | 100b0: e4d05001 ldrb r5, [r0], #1 28 | 100b4: e355007a cmp r5, #122 ; 0x7a 29 | 100b8: ca000002 bgt 100c8 30 | 100bc: e3550061 cmp r5, #97 ; 0x61 31 | 100c0: ba000000 blt 100c8 32 | 100c4: e2455020 sub r5, r5, #32 33 | 34 | 000100c8 : 35 | 100c8: e4c15001 strb r5, [r1], #1 36 | 100cc: e3550000 cmp r5, #0 37 | 100d0: 1afffff6 bne 100b0 38 | 100d4: e0410004 sub r0, r1, r4 39 | 100d8: e8bd0030 pop {r4, r5} 40 | 100dc: e12fff1e bx lr 41 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/obj.txt: -------------------------------------------------------------------------------- 1 | 2 | uppermacro: file format elf32-littlearm 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 00010074 <_start>: 8 | 10074: e59f0094 ldr r0, [pc, #148] ; 10110 <_start+0x9c> 9 | 10078: e59f1094 ldr r1, [pc, #148] ; 10114 <_start+0xa0> 10 | 1007c: e1a02001 mov r2, r1 11 | 10080: e4d03001 ldrb r3, [r0], #1 12 | 10084: e353007a cmp r3, #122 ; 0x7a 13 | 10088: ca000002 bgt 10098 <_start+0x24> 14 | 1008c: e3530061 cmp r3, #97 ; 0x61 15 | 10090: ba000000 blt 10098 <_start+0x24> 16 | 10094: e2433020 sub r3, r3, #32 17 | 10098: e4c13001 strb r3, [r1], #1 18 | 1009c: e3530000 cmp r3, #0 19 | 100a0: 1afffff6 bne 10080 <_start+0xc> 20 | 100a4: e0410002 sub r0, r1, r2 21 | 100a8: e1a02000 mov r2, r0 22 | 100ac: e3a00001 mov r0, #1 23 | 100b0: e59f105c ldr r1, [pc, #92] ; 10114 <_start+0xa0> 24 | 100b4: e3a07004 mov r7, #4 25 | 100b8: ef000000 svc 0x00000000 26 | 100bc: e59f0054 ldr r0, [pc, #84] ; 10118 <_start+0xa4> 27 | 100c0: e59f104c ldr r1, [pc, #76] ; 10114 <_start+0xa0> 28 | 100c4: e1a02001 mov r2, r1 29 | 100c8: e4d03001 ldrb r3, [r0], #1 30 | 100cc: e353007a cmp r3, #122 ; 0x7a 31 | 100d0: ca000002 bgt 100e0 <_start+0x6c> 32 | 100d4: e3530061 cmp r3, #97 ; 0x61 33 | 100d8: ba000000 blt 100e0 <_start+0x6c> 34 | 100dc: e2433020 sub r3, r3, #32 35 | 100e0: e4c13001 strb r3, [r1], #1 36 | 100e4: e3530000 cmp r3, #0 37 | 100e8: 1afffff6 bne 100c8 <_start+0x54> 38 | 100ec: e0410002 sub r0, r1, r2 39 | 100f0: e1a02000 mov r2, r0 40 | 100f4: e3a00001 mov r0, #1 41 | 100f8: e59f1014 ldr r1, [pc, #20] ; 10114 <_start+0xa0> 42 | 100fc: e3a07004 mov r7, #4 43 | 10100: ef000000 svc 0x00000000 44 | 10104: e3a00000 mov r0, #0 45 | 10108: e3a07001 mov r7, #1 46 | 1010c: ef000000 svc 0x00000000 47 | 10110: 0002011c .word 0x0002011c 48 | 10114: 0002016c .word 0x0002016c 49 | 10118: 0002014b .word 0x0002014b 50 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/upper.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ 10 | 11 | .global toupper @ Allow other files to call this routine 12 | 13 | toupper: PUSH {R4-R5} @ Save the registers we use. 14 | MOV R4, R1 15 | @ The loop is until byte pointed to by R1 is non-zero 16 | loop: LDRB R5, [R0], #1 @ load character and increment pointer 17 | @ If R5 > 'z' then goto cont 18 | CMP R5, #'z' @ is letter > 'z'? 19 | BGT cont 20 | @ Else if R5 < 'a' then goto end if 21 | CMP R5, #'a' 22 | BLT cont @ goto to end if 23 | @ if we got here then the letter is lower case, so convert it. 24 | SUB R5, #('a'-'A') 25 | cont: @ end if 26 | STRB R5, [R1], #1 @ store character to output str 27 | CMP R5, #0 @ stop on hitting a null character 28 | BNE loop @ loop if character isn't null 29 | SUB R0, R1, R4 @ get the length by subtracting the pointers 30 | POP {R4-R5} @ Restore the register we use. 31 | BX LR @ Return to caller 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 6/uppermacro.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R2 - original output string for length calc. 8 | @ R3 - current character being processed 9 | @ 10 | 11 | @ label 1 = loop 12 | @ label 2 = cont 13 | 14 | .MACRO toupper instr, outstr 15 | LDR R0, =\instr 16 | LDR R1, =\outstr 17 | MOV R2, R1 18 | @ The loop is until byte pointed to by R1 is non-zero 19 | 1: LDRB R3, [R0], #1 @ load character and increment pointer 20 | @ If R5 > 'z' then goto cont 21 | CMP R3, #'z' @ is letter > 'z'? 22 | BGT 2f 23 | @ Else if R5 < 'a' then goto end if 24 | CMP R3, #'a' 25 | BLT 2f @ goto to end if 26 | @ if we got here then the letter is lower case, so convert it. 27 | SUB R3, #('a'-'A') 28 | 2: @ end if 29 | STRB R3, [R1], #1 @ store character to output str 30 | CMP R3, #0 @ stop on hitting a null character 31 | BNE 1b @ loop if character isn't null 32 | SUB R0, R1, R2 @ get the length by subtracting the pointers 33 | .ENDM 34 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/codesnippets.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ This file contains the various code 3 | @ snippets from Chapter 6. This ensures 4 | @ they compile and gives you a chance 5 | @ to single step through them. 6 | @ They are labeled, so you can set a 7 | @ breakpoint at the one you are interested in. 8 | 9 | .global _start 10 | 11 | _start: 12 | l1: PUSH {r0, r5-r12} 13 | POP {r0, r5-r12} 14 | PUSH {r0-r4, r6, r9-r12} 15 | POP {r0-r4, r6, r9-r12} 16 | 17 | l2: BL myfunc 18 | MOV R1, #4 19 | B l3 20 | 21 | myfunc: @ do some work 22 | BX LR 23 | 24 | l3: BL myfuncb 25 | MOV R1, #4 26 | B l4 27 | 28 | myfuncb:PUSH {LR} 29 | @ do some work … 30 | BL myfuncb2 31 | @ do some more work... 32 | POP {LR} 33 | BX LR 34 | 35 | myfuncb2: @ do some work .... 36 | BX LR 37 | 38 | l4: SUB SP, #12 39 | 40 | l5: STR R0, [SP] @ Store a 41 | STR R1, [SP, #4] @ Store b 42 | STR R2, [SP, #8] @ Store c 43 | 44 | l6: ADD SP, #12 45 | 46 | l7: SUB FP, SP, #4 47 | SUB SP, #12 48 | 49 | l8: STR R0, [FP] @ Store a 50 | STR R1, [FP, #-4] @ Store b 51 | STR R2, [FP, #-8] @ Store c 52 | ADD SP, #12 53 | 54 | l9: BL SUMFN 55 | B l10 56 | 57 | @ Simple function that takes 2 parameters 58 | @ VAR1 and VAR2. The function adds them, 59 | @ storing the result in a variable SUM. 60 | @ The function returns the sum. 61 | @ It is assumed this function does other work, 62 | @ including other functions. 63 | 64 | @ Define our variables 65 | .EQU VAR1, 0 66 | .EQU VAR2, 4 67 | .EQU SUM, 8 68 | 69 | SUMFN: PUSH {R4-R12, LR} 70 | SUB SP, #12 @ room for three 32-bit values 71 | STR R0, [SP, #VAR1] @ save passed in param. 72 | STR R1, [SP, #VAR2] @ save second param. 73 | 74 | @ Do bunch of other work, but don’t change SP. 75 | 76 | LDR R4, [SP, #VAR1] 77 | LDR R5, [SP, #VAR2] 78 | ADD R6, R4, R5 79 | STR R6, [SP, #SUM] 80 | 81 | @ Do other work 82 | 83 | @ Function Epilog 84 | LDR R0, [SP, #SUM] @ load sum to return 85 | ADD SP, #12 @ Release local vars 86 | POP {R4-R12, PC} @ Restore regs and return 87 | 88 | l10: 89 | 90 | @ Setup the parameters to exit the program 91 | @ and then call Linux to do it. 92 | MOV R0, #0 @ Use 0 return code 93 | MOV R7, #1 @ Service command code 1 terminates this program 94 | SVC 0 @ Call linux to terminate the program 95 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/errno.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler version of the C errno.h files. 3 | @ All the Linux error codes for the Raspbian Buster release. 4 | @ 5 | 6 | .EQU EPERM, 1 @ Operation not permitted 7 | .EQU ENOENT, 2 @ No such file or directory 8 | .EQU ESRCH, 3 @ No such process 9 | .EQU EINTR, 4 @ Interrupted system call 10 | .EQU EIO, 5 @ I/O error 11 | .EQU ENXIO, 6 @ No such device or address 12 | .EQU E2BIG, 7 @ Argument list too long 13 | .EQU ENOEXEC, 8 @ Exec format error 14 | .EQU EBADF, 9 @ Bad file number 15 | .EQU ECHILD, 10 @ No child processes 16 | .EQU EAGAIN, 11 @ Try again 17 | .EQU ENOMEM, 12 @ Out of memory 18 | .EQU EACCES, 13 @ Permission denied 19 | .EQU EFAULT, 14 @ Bad address 20 | .EQU ENOTBLK, 15 @ Block device required 21 | .EQU EBUSY, 16 @ Device or resource busy 22 | .EQU EEXIST, 17 @ File exists 23 | .EQU EXDEV, 18 @ Cross-device link 24 | .EQU ENODEV, 19 @ No such device 25 | .EQU ENOTDIR, 20 @ Not a directory 26 | .EQU EISDIR, 21 @ Is a directory 27 | .EQU EINVAL, 22 @ Invalid argument 28 | .EQU ENFILE, 23 @ File table overflow 29 | .EQU EMFILE, 24 @ Too many open files 30 | .EQU ENOTTY, 25 @ Not a typewriter 31 | .EQU ETXTBSY, 26 @ Text file busy 32 | .EQU EFBIG, 27 @ File too large 33 | .EQU ENOSPC, 28 @ No space left on device 34 | .EQU ESPIPE, 29 @ Illegal seek 35 | .EQU EROFS, 30 @ Read-only file system 36 | .EQU EMLINK, 31 @ Too many links 37 | .EQU EPIPE, 32 @ Broken pipe 38 | .EQU EDOM, 33 @ Math argument out of domain of func 39 | .EQU ERANGE, 34 @ Math result not representable 40 | .EQU EDEADLK, 35 @ Resource deadlock would occur 41 | .EQU ENAMETOOLONG, 36 @ File name too long 42 | .EQU ENOLCK, 37 @ No record locks available 43 | .EQU ENOSYS, 38 @ Invalid system call number 44 | .EQU ENOTEMPTY, 39 @ Directory not empty 45 | .EQU ELOOP, 40 @ Too many symbolic links encountered 46 | .EQU ENOMSG, 42 @ No message of desired type 47 | .EQU EIDRM, 43 @ Identifier removed 48 | .EQU ECHRNG, 44 @ Channel number out of range 49 | .EQU EL2NSYNC, 45 @ Level 2 not synchronized 50 | .EQU EL3HLT, 46 @ Level 3 halted 51 | .EQU EL3RST, 47 @ Level 3 reset 52 | .EQU ELNRNG, 48 @ Link number out of range 53 | .EQU EUNATCH, 49 @ Protocol driver not attached 54 | .EQU ENOCSI, 50 @ No CSI structure available 55 | .EQU EL2HLT, 51 @ Level 2 halted 56 | .EQU EBADE, 52 @ Invalid exchange 57 | .EQU EBADR, 53 @ Invalid request descriptor 58 | .EQU EXFULL, 54 @ Exchange full 59 | .EQU ENOANO, 55 @ No anode 60 | .EQU EBADRQC, 56 @ Invalid request code 61 | .EQU EBADSLT, 57 @ Invalid slot 62 | .EQU EBFONT, 59 @ Bad font file format 63 | .EQU ENOSTR, 60 @ Device not a stream 64 | .EQU ENODATA, 61 @ No data available 65 | .EQU ETIME, 62 @ Timer expired 66 | .EQU ENOSR, 63 @ Out of streams resources 67 | .EQU ENONET, 64 @ Machine is not on the network 68 | .EQU ENOPKG, 65 @ Package not installed 69 | .EQU EREMOTE, 66 @ Object is remote 70 | .EQU ENOLINK, 67 @ Link has been severed 71 | .EQU EADV, 68 @ Advertise error 72 | .EQU ESRMNT, 69 @ Srmount error 73 | .EQU ECOMM, 70 @ Communication error on send 74 | .EQU EPROTO, 71 @ Protocol error 75 | .EQU EMULTIHOP, 72 @ Multihop attempted 76 | .EQU EDOTDOT, 73 @ RFS specific error 77 | .EQU EBADMSG, 74 @ Not a data message 78 | .EQU EOVERFLOW, 75 @ Value too large for defined data type 79 | .EQU ENOTUNIQ, 76 @ Name not unique on network 80 | .EQU EBADFD, 77 @ File descriptor in bad state 81 | .EQU EREMCHG, 78 @ Remote address changed 82 | .EQU ELIBACC, 79 @ Can not access a needed shared library 83 | .EQU ELIBBAD, 80 @ Accessing a corrupted shared library 84 | .EQU ELIBSCN, 81 @ .lib section in a.out corrupted 85 | .EQU ELIBMAX, 82 @ Attempting to link in too many shared libraries 86 | .EQU ELIBEXEC, 83 @ Cannot exec a shared library directly 87 | .EQU EILSEQ, 84 @ Illegal byte sequence 88 | .EQU ERESTART, 85 @ Interrupted system call should be restarted 89 | .EQU ESTRPIPE, 86 @ Streams pipe error 90 | .EQU EUSERS, 87 @ Too many users 91 | .EQU ENOTSOCK, 88 @ Socket operation on non-socket 92 | .EQU EDESTADDRREQ, 89 @ Destination address required 93 | .EQU EMSGSIZE, 90 @ Message too long 94 | .EQU EPROTOTYPE, 91 @ Protocol wrong type for socket 95 | .EQU ENOPROTOOPT,92 @ Protocol not available 96 | .EQU EPROTONOSUPPORT, 93 @ Protocol not supported 97 | .EQU ESOCKTNOSUPPORT, 94 @ Socket type not supported 98 | .EQU EOPNOTSUPP, 95 @ Operation not supported on transport endpoint 99 | .EQU EPFNOSUPPORT, 96 @ Protocol family not supported 100 | .EQU EAFNOSUPPORT, 97 @ Address family not supported by protocol 101 | .EQU EADDRINUSE, 98 @ Address already in use 102 | .EQU EADDRNOTAVAIL, 99 @ Cannot assign requested address 103 | .EQU ENETDOWN, 100 @ Network is down 104 | .EQU ENETUNREACH,101 @ Network is unreachable 105 | .EQU ENETRESET, 102 @ Network dropped connection because of reset 106 | .EQU ECONNABORTED, 103 @ Software caused connection abort 107 | .EQU ECONNRESET, 104 @ Connection reset by peer 108 | .EQU ENOBUFS, 105 @ No buffer space available 109 | .EQU EISCONN, 106 @ Transport endpoint is already connected 110 | .EQU ENOTCONN, 107 @ Transport endpoint is not connected 111 | .EQU ESHUTDOWN, 108 @ Cannot send after transport endpoint shutdown 112 | .EQU ETOOMANYREFS, 109 @ Too many references: cannot splice 113 | .EQU ETIMEDOUT, 110 @ Connection timed out 114 | .EQU ECONNREFUSED, 111 @ Connection refused 115 | .EQU EHOSTDOWN, 112 @ Host is down 116 | .EQU EHOSTUNREACH, 113 @ No route to host 117 | .EQU EALREADY, 114 @ Operation already in progress 118 | .EQU EINPROGRESS,115 @ Operation now in progress 119 | .EQU ESTALE, 116 @ Stale file handle 120 | .EQU EUCLEAN, 117 @ Structure needs cleaning 121 | .EQU ENOTNAM, 118 @ Not a XENIX named type file 122 | .EQU ENAVAIL, 119 @ No XENIX semaphores available 123 | .EQU EISNAM, 120 @ Is a named type file 124 | .EQU EREMOTEIO, 121 @ Remote I/O error 125 | .EQU EDQUOT, 122 @ Quota exceeded 126 | .EQU ENOMEDIUM, 123 @ No medium found 127 | .EQU EMEDIUMTYPE,124 @ Wrong medium type 128 | .EQU ECANCELED, 125 @ Operation Canceled 129 | .EQU ENOKEY, 126 @ Required key not available 130 | .EQU EKEYEXPIRED,127 @ Key has expired 131 | .EQU EKEYREVOKED,128 @ Key has been revoked 132 | .EQU EKEYREJECTED, 129 @ Key was rejected by service 133 | .EQU EOWNERDEAD, 130 @ Owner died 134 | .EQU ENOTRECOVERABLE, 131 @ State not recoverable 135 | .EQU ERFKILL, 132 @ Operation not possible due to RF-kill 136 | .EQU EHWPOISON, 133 @ Memory page has hardware error 137 | 138 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/fileio.s: -------------------------------------------------------------------------------- 1 | @ Various macros to perform file I/O 2 | 3 | @ The fd parameter needs to be a register. 4 | @ Uses R0, R1, R7. 5 | @ Return code is in R0. 6 | 7 | .include "unistd.s" 8 | 9 | .equ O_RDONLY, 0 10 | .equ O_WRONLY, 1 11 | .equ O_CREAT, 0100 12 | .equ S_RDWR, 0666 13 | 14 | .macro openFile fileName, flags 15 | ldr r0, =\fileName 16 | mov r1, #\flags 17 | mov r2, #S_RDWR @ RW access rights 18 | mov r7, #sys_open 19 | svc 0 20 | .endm 21 | .macro readFile fd, buffer, length 22 | mov r0, \fd @ file descriptor 23 | ldr r1, =\buffer 24 | mov r2, #\length 25 | mov r7, #sys_read 26 | svc 0 27 | .endm 28 | .macro writeFile fd, buffer, length 29 | mov r0, \fd @ file descriptor 30 | ldr r1, =\buffer 31 | mov r2, \length 32 | mov r7, #sys_write 33 | svc 0 34 | .endm 35 | .macro flushClose fd 36 | @fsync syscall 37 | mov r0, \fd 38 | mov r7, #sys_fsync 39 | svc 0 40 | 41 | @close syscall 42 | mov r0, \fd 43 | mov r7, #sys_close 44 | svc 0 45 | .endm 46 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/main.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case by calling a function. 4 | @ 5 | @ R0-R2, R7 - used by macros to call linux 6 | @ R8 - input file descriptor 7 | @ R9 - output file descriptor 8 | @ R10 - number of characters read 9 | @ 10 | 11 | .include "fileio.s" 12 | 13 | .equ BUFFERLEN, 250 14 | 15 | .global _start @ Provide program starting address to linker 16 | 17 | _start: openFile inFile, O_RDONLY 18 | MOVS R8, R0 @ save file descriptor 19 | BPL nxtfil @ pos number file opened ok 20 | MOV R1, #1 @ stdout 21 | LDR R2, =inpErrsz @ Error msg 22 | LDR R2, [R2] 23 | writeFile R1, inpErr, R2 @ print the error 24 | B exit 25 | 26 | nxtfil: openFile outFile, O_CREAT+O_WRONLY 27 | MOVS R9, R0 @ save file descriptor 28 | BPL loop @ pos number file opened ok 29 | MOV R1, #1 30 | LDR R2, =outErrsz 31 | LDR R2, [R2] 32 | writeFile R1, outErr, R2 33 | B exit 34 | 35 | @ loop through file until done. 36 | loop: readFile R8, buffer, BUFFERLEN 37 | MOV R10, R0 @ Keep the length read 38 | MOV R1, #0 @ Null terminator for string 39 | 40 | @ setup call to toupper and call function 41 | LDR R0, =buffer @ first param for toupper 42 | STRB R1, [R0, R10] @ put null at end of string. 43 | LDR R1, =outBuf 44 | BL toupper 45 | 46 | writeFile R9, outBuf, R10 47 | 48 | CMP R10, #BUFFERLEN 49 | BEQ loop 50 | 51 | flushClose R8 52 | flushClose R9 53 | 54 | @ Setup the parameters to exit the program 55 | @ and then call Linux to do it. 56 | exit: MOV R0, #0 @ Use 0 return code 57 | MOV R7, #1 @ Service command code 1 terminates this program 58 | SVC 0 @ Call linux to terminate the program 59 | 60 | .data 61 | inFile: .asciz "main.s" 62 | outFile: .asciz "upper.txt" 63 | buffer: .fill BUFFERLEN + 1, 1, 0 64 | outBuf: .fill BUFFERLEN + 1, 1, 0 65 | inpErr: .asciz "Failed to open input file.\n" 66 | inpErrsz: .word .-inpErr 67 | outErr: .asciz "Failed to open output file.\n" 68 | outErrsz: .word .-outErr 69 | 70 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/makefile: -------------------------------------------------------------------------------- 1 | UPPEROBJS = main.o upper.o 2 | 3 | ifdef DEBUG 4 | DEBUGFLGS = -g 5 | else 6 | DEBUGFLGS = 7 | endif 8 | LSTFLGS = 9 | 10 | all: upper 11 | 12 | %.o : %.s 13 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 14 | 15 | upper: $(UPPEROBJS) 16 | ld -o upper $(UPPEROBJS) 17 | 18 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/unistd.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Defines for the Linux system calls. 3 | @ This list is from Raspbian Buster 4 | @ 5 | 6 | .EQU sys_restart_syscall, 0 @ restart a system call after interruption by a stop signal 7 | .EQU sys_exit, 1 @ cause normal process termination 8 | .EQU sys_fork, 2 @ create a child process 9 | .EQU sys_read, 3 @ read from a file descriptor 10 | .EQU sys_write, 4 @ write to a file descriptor 11 | .EQU sys_open, 5 @ open and possibly create a file 12 | .EQU sys_close, 6 @ close a file descriptor 13 | .EQU sys_creat, 8 @ create a new file or rewrite an existing one 14 | .EQU sys_link, 9 @ make a new name for a file 15 | .EQU sys_unlink, 10 @ delete a name and possibly the file it refers to 16 | .EQU sys_execve, 11 @ execute program 17 | .EQU sys_chdir, 12 @ change working directory 18 | .EQU sys_mknod, 14 @ create a special or ordinary file 19 | .EQU sys_chmod, 15 @ change file mode bits 20 | .EQU sys_lchown, 16 @ change the owner and group of a symbolic link 21 | .EQU sys_lseek, 19 @ reposition read/write file offset 22 | .EQU sys_getpid, 20 @ get process identification 23 | .EQU sys_mount, 21 @ mount filesystem 24 | .EQU sys_setuid, 23 @ set user identity 25 | .EQU sys_getuid, 24 @ get user identity 26 | .EQU sys_ptrace, 26 @ process trace 27 | .EQU sys_pause, 29 @ wait for signal 28 | .EQU sys_access, 33 @ check user's permissions for a file 29 | .EQU sys_nice, 34 @ change process priority 30 | .EQU sys_sync, 36 @ commit filesystem caches to disk 31 | .EQU sys_kill, 37 @ send signal to a process 32 | .EQU sys_rename, 38 @ change the name or location of a file 33 | .EQU sys_mkdir, 39 @ create a directory 34 | .EQU sys_rmdir, 40 @ delete a directory 35 | .EQU sys_dup, 41 @ duplicate a file descriptor 36 | .EQU sys_pipe, 42 @ create pipe 37 | .EQU sys_times, 43 @ get process times 38 | .EQU sys_brk, 45 @ change data segment size 39 | .EQU sys_setgid, 46 @ set group identity 40 | .EQU sys_getgid, 47 @ get group identity 41 | .EQU sys_geteuid, 49 @ get user identity 42 | .EQU sys_getegid, 50 @ get group identity 43 | .EQU sys_acct, 51 @ switch process accounting on or off 44 | .EQU sys_umount2, 52 @ unmount filesystem 45 | .EQU sys_ioctl, 54 @ control device 46 | .EQU sys_fcntl, 55 @ manipulate file descriptor 47 | .EQU sys_setpgid, 57 @ set process group 48 | .EQU sys_umask, 60 @ set file mode creation mask 49 | .EQU sys_chroot, 61 @ change root directory 50 | .EQU sys_ustat, 62 @ get filesystem statistics 51 | .EQU sys_dup2, 63 @ duplicate a file descriptor 52 | .EQU sys_getppid, 64 @ get the parent process ID 53 | .EQU sys_getpgrp, 65 @ get process group 54 | .EQU sys_setsid, 66 @ creates a session and sets the process group ID 55 | .EQU sys_sigaction, 67 @ examine and change a signal action 56 | .EQU sys_setreuid, 70 @ set real and/or effective user ID 57 | .EQU sys_setregid, 71 @ set real and/or effective group ID 58 | .EQU sys_sigsuspend, 72 @ wait for a signal 59 | .EQU sys_sigpending, 73 @ examine pending signals 60 | .EQU sys_sethostname, 74 @ set hostname 61 | .EQU sys_setrlimit, 75 @ control maximum resource consumption 62 | .EQU sys_getrusage, 77 @ get resource usage 63 | .EQU sys_gettimeofday, 78 @ get time 64 | .EQU sys_settimeofday, 79 @ set time 65 | .EQU sys_getgroups, 80 @ get list of supplementary group IDs 66 | .EQU sys_setgroups, 81 @ set list of supplementary group IDs 67 | .EQU sys_symlink, 83 @ make a new name for a file 68 | .EQU sys_readlink, 85 @ read value of a symbolic link 69 | .EQU sys_uselib, 86 @load shared library 70 | .EQU sys_swapon, 87 @ start swapping to file/device 71 | .EQU sys_reboot, 88 @ reboot 72 | .EQU sys_munmap, 91 @ unmap files or devices into memory 73 | .EQU sys_truncate, 92 @ truncate a file to a specified length 74 | .EQU sys_ftruncate, 93 @ truncate a file to a specified length 75 | .EQU sys_fchmod, 94 @ change permissions of a file 76 | .EQU sys_fchown, 95 @ change ownership of a file 77 | .EQU sys_getpriority, 96 @ get program scheduling priority 78 | .EQU sys_setpriority, 97 @ set program scheduling priority 79 | .EQU sys_statfs, 99 @ get filesystem statistics 80 | .EQU sys_fstatfs, 100 @ get filesystem statistics 81 | .EQU sys_syslog, 103 @ read and/or clear kernel message ring buffer; set console_loglevel 82 | .EQU sys_setitimer, 104 @ set value of an interval timer 83 | .EQU sys_getitimer, 105 @ get value of an interval timer 84 | .EQU sys_stat, 106 @ get file status 85 | .EQU sys_lstat, 107 @ get file status 86 | .EQU sys_fstat, 108 @ get file status 87 | .EQU sys_vhangup, 111 @ virtually hangup the current terminal 88 | .EQU sys_wait4, 114 @ wait for process to change state, BSD style 89 | .EQU sys_swapoff, 115 @ stop swapping to file/device 90 | .EQU sys_sysinfo, 116 @ return system information 91 | .EQU sys_fsync, 118 @ synchronize a file's in-core state with storage 92 | .EQU sys_sigreturn, 119 @ return from signal handler and cleanup stack frame 93 | .EQU sys_clone, 120 @ create a child process 94 | .EQU sys_setdomainname, 121 @ set NIS domain name 95 | .EQU sys_uname, 122 @ get name and information about current kernel 96 | .EQU sys_adjtimex, 124 @ tune kernel clock 97 | .EQU sys_mprotect, 125 @ set protection on a region of memory 98 | .EQU sys_sigprocmask, 126 @ examine and change blocked signals 99 | .EQU sys_init_module, 128 @ load a kernel module 100 | .EQU sys_delete_module, 129 @ unload a kernel module 101 | .EQU sys_quotactl, 131 @ manipulate disk quotas 102 | .EQU sys_getpgid, 132 @ get process group 103 | .EQU sys_fchdir, 133 @ change working directory 104 | .EQU sys_bdflush, 134 @ start, flush, or tune buffer-dirty-flush daemon 105 | .EQU sys_sysfs, 135 @ get filesystem type information 106 | .EQU sys_personality, 136 @ set the process execution domain 107 | .EQU sys_setfsuid, 138 @ set user identity used for filesystem checks 108 | .EQU sys_setfsgid, 139 @ set group identity used for filesystem checks 109 | .EQU sys__llseek, 140 @ reposition read/write file offset 110 | .EQU sys_getdents, 141 @ get directory entries 111 | .EQU sys__newselect, 142 @ synchronous I/O multiplexing 112 | .EQU sys_flock, 143 @ apply or remove an advisory lock on an open file 113 | .EQU sys_msync, 144 @ synchronize a file with a memory map 114 | .EQU sys_readv, 145 @ read data into multiple buffers 115 | .EQU sys_writev, 146 @ write data into multiple buffers 116 | .EQU sys_getsid, 147 @ get session ID 117 | .EQU sys_fdatasync, 148 @ synchronize a file's in-core state with storage device 118 | .EQU sys__sysctl, 149 @ read/write system parameters 119 | .EQU sys_mlock, 150 @ lock memory 120 | .EQU sys_munlock, 151 @ unlock memory 121 | .EQU sys_mlockall, 152 @ lock memory 122 | .EQU sys_munlockall, 153 @ unlock memory 123 | .EQU sys_sched_setparam, 154 @ set scheduling parameters 124 | .EQU sys_sched_getparam, 155 @ get scheduling parameters 125 | .EQU sys_sched_setscheduler, 156 @ set and get scheduling policy/parameters 126 | .EQU sys_sched_getscheduler, 157 @ set and get scheduling policy/parameters 127 | .EQU sys_sched_yield, 158 @ yield the processor 128 | .EQU sys_sched_get_priority_max, 159 @ get static priority max 129 | .EQU sys_sched_get_priority_min, 160 @ get static priority min 130 | .EQU sys_sched_rr_get_interval, 161 @ get the SCHED_RR interval for the named process 131 | .EQU sys_nanosleep, 162 @ high-resolution sleep 132 | .EQU sys_mremap, 163 @ remap a virtual memory address 133 | .EQU sys_setresuid, 164 @ set real, effective and saved user ID 134 | .EQU sys_getresuid, 165 @ get real, effective and saved user ID 135 | .EQU sys_poll, 168 @ wait for some event on a file descriptor 136 | .EQU sys_nfsservctl, 169 @ syscall interface to kernel nfs daemon 137 | .EQU sys_setresgid, 170 @ set real, effective and saved group ID 138 | .EQU sys_getresgid, 171 @ get real, effective and saved group ID 139 | .EQU sys_prctl, 172 @ operations on a process 140 | .EQU sys_rt_sigreturn, 173 @ return from signal handler and cleanup stack frame 141 | .EQU sys_rt_sigaction, 174 @ examine and change a signal action 142 | .EQU sys_rt_sigprocmask, 175 @ examine and change blocked signals 143 | .EQU sys_rt_sigpending, 176 @ examine pending signals 144 | .EQU sys_rt_sigtimedwait, 177 @ synchronously wait for queued signals 145 | .EQU sys_rt_sigqueueinfo, 178 @ queue a signal and data 146 | .EQU sys_rt_sigsuspend, 179 @ wait for a signal 147 | .EQU sys_pread64, 180 @ read from a file descriptor at a given offset 148 | .EQU sys_pwrite64, 181 @ write to a file descriptor at a given offset 149 | .EQU sys_chown, 182 @ change ownership of a file 150 | .EQU sys_getcwd, 183 @ get current working directory 151 | .EQU sys_capget, 184 @ get capabilities of thread(s) 152 | .EQU sys_capset, 185 @ set capabilities of thread(s) 153 | .EQU sys_sigaltstack, 186 @ set and/or get signal stack context 154 | .EQU sys_sendfile, 187 @ transfer data between file descriptors 155 | .EQU sys_vfork, 190 @ create a child process and block parent 156 | .EQU sys_ugetrlimit, 191 @ get resource limits 157 | .EQU sys_mmap2, 192 @ map files or devices into memory 158 | .EQU sys_truncate64, 193 @ truncate a file to a specified length 159 | .EQU sys_ftruncate64, 194 @ truncate a file to a specified length 160 | .EQU sys_stat64, 195 @ get file status 161 | .EQU sys_lstat64, 196 @ get file status 162 | .EQU sys_fstat64, 197 @ get file status 163 | .EQU sys_lchown32, 198 @ change ownership of a file 164 | .EQU sys_getuid32, 199 @ get user identity 165 | .EQU sys_getgid32, 200 @ get group identity 166 | .EQU sys_geteuid32, 201 @ get user identity 167 | .EQU sys_getegid32, 202 @ get group identity 168 | .EQU sys_setreuid32, 203 @ set real and/or effective user ID 169 | .EQU sys_setregid32, 204 @ set real and/or effective group ID 170 | .EQU sys_getgroups32, 205 @ get list of supplementary group IDs 171 | .EQU sys_setgroups32, 206 @ set list of supplementary group IDs 172 | .EQU sys_fchown32, 207 @ change ownership of a file 173 | .EQU sys_setresuid32, 208 @ set real, effective and saved user ID 174 | .EQU sys_getresuid32, 209 @ get real, effective and saved user ID 175 | .EQU sys_setresgid32, 210 @ set real, effective and saved group ID 176 | .EQU sys_getresgid32, 211 @ get real, effective and saved group ID 177 | .EQU sys_chown32, 212 @ change ownership of a file 178 | .EQU sys_setuid32, 213 @ set user identity 179 | .EQU sys_setgid32, 214 @ set group identity 180 | .EQU sys_setfsuid32, 215 @ set user identity used for filesystem checks 181 | .EQU sys_setfsgid32, 216 @ set group identity used for filesystem checks 182 | .EQU sys_getdents64, 217 @ get directory entries 183 | .EQU sys_pivot_root, 218 @ change the root filesystem 184 | .EQU sys_mincore, 219 @ determine whether pages are resident in memory 185 | .EQU sys_madvise, 220 @ give advice about use of memory 186 | .EQU sys_fcntl64, 221 @ manipulate file descriptor 187 | .EQU sys_gettid, 224 @ get thread identification 188 | .EQU sys_readahead, 225 @ initiate file readahead into page cache 189 | .EQU sys_setxattr, 226 @ set an extended attribute value 190 | .EQU sys_lsetxattr, 227 @ set an extended attribute value 191 | .EQU sys_fsetxattr, 228 @ set an extended attribute value 192 | .EQU sys_getxattr, 229 @ retrieve an extended attribute value 193 | .EQU sys_lgetxattr, 230 @ retrieve an extended attribute value 194 | .EQU sys_fgetxattr, 231 @ retrieve an extended attribute value 195 | .EQU sys_listxattr, 232 @ list extended attribute names 196 | .EQU sys_llistxattr, 233 @ list extended attribute names 197 | .EQU sys_flistxattr, 234 @ list extended attribute names 198 | .EQU sys_removexattr, 235 @ remove an extended attribute 199 | .EQU sys_lremovexattr, 236 @ remove an extended attribute 200 | .EQU sys_fremovexattr, 237 @ remove an extended attribute 201 | .EQU sys_tkill, 238 @ send a signal to a thread 202 | .EQU sys_sendfile64, 239 @ transfer data between file descriptors 203 | .EQU sys_futex, 240 @ fast user-space locking 204 | .EQU sys_sched_setaffinity, 241 @ set a thread's CPU affinity mask 205 | .EQU sys_sched_getaffinity, 242 @ get a thread's CPU affinity mask 206 | .EQU sys_io_setup, 243 @ create an asynchronous I/O context 207 | .EQU sys_io_destroy, 244 @ destroy an asynchronous I/O context 208 | .EQU sys_io_getevents, 245 @ read asynchronous I/O events from the completion queue 209 | .EQU sys_io_submit, 246 @ submit asynchronous I/O blocks for processing 210 | .EQU sys_io_cancel, 247 @ cancel an outstanding asynchronous I/O operation 211 | .EQU sys_exit_group, 248 @ exit all threads in a process 212 | .EQU sys_lookup_dcookie, 249 @ return a directory entry's path 213 | .EQU sys_epoll_create, 250 @ open an epoll file descriptor 214 | .EQU sys_epoll_ctl, 251 @ control interface for an epoll file descriptor 215 | .EQU sys_epoll_wait, 252 @ wait for an I/O event on an epoll file descriptor 216 | .EQU sys_remap_file_pages, 253 @ create a nonlinear file mapping 217 | .EQU sys_set_tid_address, 256 @ set pointer to thread ID 218 | .EQU sys_timer_create, 257 @ create a POSIX per-process timer 219 | .EQU sys_timer_settime, 258 @arm/disarm state of POSIX per-process timer 220 | .EQU sys_timer_gettime, 259 @ fetch state of POSIX per-process timer 221 | .EQU sys_timer_getoverrun, 260 @ get overrun count for a POSIX per-process timer 222 | .EQU sys_timer_delete, 261 @ delete a POSIX per-process timer 223 | .EQU sys_clock_settime, 262 @ clock and timer functions 224 | .EQU sys_clock_gettime, 263 @ clock and timer functions 225 | .EQU sys_clock_getres, 264 @ clock and timer functions 226 | .EQU sys_clock_nanosleep, 265 @ high-resolution sleep with specifiable clock 227 | .EQU sys_statfs64, 266 @ get filesystem statistics 228 | .EQU sys_fstatfs64, 267 @ get filesystem statistics 229 | .EQU sys_tgkill, 268 @ send a signal to a thread 230 | .EQU sys_utimes, 269 @ change file last access and modification times 231 | .EQU sys_arm_fadvise64_64, 270 @ predeclare an access pattern for file data 232 | .EQU sys_pciconfig_iobase, 271 @ pci device information handling 233 | .EQU sys_pciconfig_read, 272 @ pci device information handling 234 | .EQU sys_pciconfig_write, 273 @ pci device information handling 235 | .EQU sys_mq_open, 274 @ open a message queue 236 | .EQU sys_mq_unlink, 275 @ remove a message queue 237 | .EQU sys_mq_timedsend, 276 @ send a message to a message queue 238 | .EQU sys_mq_timedreceive, 277 @ receive a message from a message queue 239 | .EQU sys_mq_notify, 278 @ register for notification when a message is available 240 | .EQU sys_mq_getsetattr, 279 @ get/set message queue attributes 241 | .EQU sys_waitid, 280 @ wait for a child process to change state 242 | .EQU sys_socket, 281 @ create an endpoint for communication 243 | .EQU sys_bind, 282 @ bind a name to a socket 244 | .EQU sys_connect, 283 @ initiate a connection on a socket 245 | .EQU sys_listen, 284 @ listen for connections on a socket 246 | .EQU sys_accept, 285 @ accept a connection on a socket 247 | .EQU sys_getsockname, 286 @ get socket name 248 | .EQU sys_getpeername, 287 @ get name of connected peer socket 249 | .EQU sys_socketpair, 288 @ create a pair of connected sockets 250 | .EQU sys_send, 289 @ send a message on a socket 251 | .EQU sys_sendto, 290 @ send a message on a socket 252 | .EQU sys_recv, 291 @ receive a message from a socket 253 | .EQU sys_recvfrom, 292 @ receive a message from a socket 254 | .EQU sys_shutdown, 293 @ shut down part of a full-duplex connection 255 | .EQU sys_setsockopt, 294 @ set options on sockets 256 | .EQU sys_getsockopt, 295 @ get options on sockets 257 | .EQU sys_sendmsg, 296 @ send a message on a socket using a message structure 258 | .EQU sys_recvmsg, 297 @ receive a message from a socket 259 | .EQU sys_semop, 298 @ System V semaphore operations 260 | .EQU sys_semget, 299 @ get a System V semaphore set identifier 261 | .EQU sys_semctl, 300 @ System V semaphore control operations 262 | .EQU sys_msgsnd, 301 @ XSI message send operation 263 | .EQU sys_msgrcv, 302 @ XSI message receive operation 264 | .EQU sys_msgget, 303 @ get a System V message queue identifier 265 | .EQU sys_msgctl, 304 @ System V message control operations 266 | .EQU sys_shmat, 305 @ XSI shared memory attach operation 267 | .EQU sys_shmdt, 306 @ XSI shared memory detach operation 268 | .EQU sys_shmget, 307 @ allocates a System V shared memory segment 269 | .EQU sys_shmctl, 308 @ System V shared memory control 270 | .EQU sys_add_key, 309 @ add a key to the kernel's key management facility 271 | .EQU sys_request_key, 310 @ request a key from the kernel's key management facility 272 | .EQU sys_keyctl, 311 @ manipulate the kernel's key management facility 273 | .EQU sys_semtimedop, 312 @ System V semaphore operations 274 | .EQU sys_vserver, 313 @ Unimplemented 275 | .EQU sys_ioprio_set, 314 @ set I/O scheduling class and priority 276 | .EQU sys_ioprio_get, 315 @ get I/O scheduling class and priority 277 | .EQU sys_inotify_init, 316 @ initialize an inotify instance 278 | .EQU sys_inotify_add_watch, 317 @ add a watch to an initialized inotify instance 279 | .EQU sys_inotify_rm_watch, 318 @ remove an existing watch from an inotify instance 280 | .EQU sys_mbind, 319 @ set memory policy for a memory range 281 | .EQU sys_get_mempolicy, 320 @ retrieve NUMA memory policy for a thread 282 | .EQU sys_set_mempolicy, 321 @ set default NUMA memory policy for a thread and its children 283 | .EQU sys_openat, 322 @ open file relative to directory file descriptor 284 | .EQU sys_mkdirat, 323 @ create a directory 285 | .EQU sys_mknodat, 324 @ create a special or ordinary file 286 | .EQU sys_fchownat, 325 @ change owner and group of a file relative to directory file descriptor 287 | .EQU sys_futimesat, 326 @ change timestamps of a file relative to a directory file descriptor 288 | .EQU sys_fstatat64, 327 @ get file status 289 | .EQU sys_unlinkat, 328 @ delete a name and possibly the file it refers to 290 | .EQU sys_renameat, 329 @ change the name or location of a file 291 | .EQU sys_linkat, 330 @ make a new name for a file 292 | .EQU sys_symlinkat, 331 @ make a new name for a file 293 | .EQU sys_readlinkat, 332 @ read value of a symbolic link 294 | .EQU sys_fchmodat, 333 @ change permissions of a file 295 | .EQU sys_faccessat, 334 @ determine accessibility of a file relative to directory file descriptor 296 | .EQU sys_pselect6, 335 @ synchronous I/O multiplexing 297 | .EQU sys_ppoll, 336 @ wait for some event on a file descriptor 298 | .EQU sys_unshare, 337 @ run program with some namespaces unshared from parent 299 | .EQU sys_set_robust_list, 338 @ set list of robust futexes 300 | .EQU sys_get_robust_list, 339 @ get list of robust futexes 301 | .EQU sys_splice, 340 @ splice data to/from a pipe 302 | .EQU sys_arm_sync_file_range, 341 @ sync a file segment with disk 303 | .EQU sys_tee, 342 @ duplicating pipe content 304 | .EQU sys_vmsplice, 343 @ splice user pages to/from a pipe 305 | .EQU sys_move_pages, 344 @ move individual pages of a process to another node 306 | .EQU sys_getcpu, 345 @ determine CPU and NUMA node on which the calling thread is running 307 | .EQU sys_epoll_pwait, 346 @ wait for an I/O event on an epoll file descriptor 308 | .EQU sys_kexec_load, 347 @ load a new kernel for later execution 309 | .EQU sys_utimensat, 348 @ change file timestamps with nanosecond precision 310 | .EQU sys_signalfd, 349 @ create a file descriptor for accepting signals 311 | .EQU sys_timerfd_create, 350 @ timers that notify via file descriptors 312 | .EQU sys_eventfd, 351 @ create a file descriptor for event notification 313 | .EQU sys_fallocate, 352 @ manipulate file space 314 | .EQU sys_timerfd_settime, 353 @ timers that notify via file descriptors 315 | .EQU sys_timerfd_gettime, 354 @ timers that notify via file descriptors 316 | .EQU sys_signalfd4, 355 @ create a file descriptor for accepting signals 317 | .EQU sys_eventfd2, 356 @ create a file descriptor for event notification 318 | .EQU sys_epoll_create1, 357 @ open an epoll file descriptor 319 | .EQU sys_dup3, 358 @ duplicate a file descriptor 320 | .EQU sys_pipe2, 359 @ create pipe 321 | .EQU sys_inotify_init1, 360 @ initialize an inotify instance 322 | .EQU sys_preadv, 361 @ read data into multiple buffers 323 | .EQU sys_pwritev, 362 @ write data into multiple buffers 324 | .EQU sys_rt_tgsigqueueinfo, 363 @ queue a signal and data 325 | .EQU sys_perf_event_open, 364 @ set up performance monitoring 326 | .EQU sys_recvmmsg, 365 @ receive multiple messages on a socket 327 | .EQU sys_accept4, 366 @ accept a connection on a socket 328 | .EQU sys_fanotify_init, 367 @ create and initialize fanotify group 329 | .EQU sys_fanotify_mark, 368 @ add, remove, or modify an fanotify mark on a filesystem object 330 | .EQU sys_prlimit64, 369 @ get/set resource limits 331 | .EQU sys_name_to_handle_at, 370 @ obtain handle for a pathname 332 | .EQU sys_open_by_handle_at, 371 @ open file via a handle 333 | .EQU sys_clock_adjtime, 372 @ tune kernel clock 334 | .EQU sys_syncfs, 373 @ commit filesystem caches to disk 335 | .EQU sys_sendmmsg, 374 @ send multiple messages on a socket 336 | .EQU sys_setns, 375 @ reassociate thread with a namespace 337 | .EQU sys_process_vm_readv, 376 @ transfer data between process address spaces 338 | .EQU sys_process_vm_writev, 377 @ transfer data between process address spaces 339 | .EQU sys_kcmp, 378 @ compare two processes to determine if they share a kernel resource 340 | .EQU sys_finit_module, 379 @ load a kernel module 341 | .EQU sys_sched_setattr, 380 @ set scheduling policy and attributes 342 | .EQU sys_sched_getattr, 381 @ get scheduling policy and attributes 343 | .EQU sys_renameat2, 382 @ change the name or location of a file 344 | .EQU sys_seccomp, 383 @ operate on Secure Computing state of the process 345 | .EQU sys_getrandom, 384 @ obtain a series of random bytes 346 | .EQU sys_memfd_create, 385 @ create an anonymous file 347 | .EQU sys_bpf, 386 @ perform a command on an extended BPF map or program 348 | .EQU sys_execveat, 387 @ execute program relative to a directory file descriptor 349 | .EQU sys_userfaultfd, 388 @ create a file descriptor for handling page faults in user space 350 | .EQU sys_membarrier, 389 @ issue memory barriers on a set of threads 351 | .EQU sys_mlock2, 390 @ lock memory 352 | .EQU sys_copy_file_range, 391 @ Copy a range of data from one file to another 353 | .EQU sys_preadv2, 392 @ read data into multiple buffers 354 | .EQU sys_pwritev2, 393 @ write data into multiple buffers 355 | .EQU sys_pkey_mprotect, 394 @ set protection on a region of memory 356 | .EQU sys_pkey_alloc, 395 @ allocate a protection key 357 | .EQU sys_pkey_free, 396 @ free a protection key 358 | .EQU sys_statx, 397 @ get file status (extended) 359 | .EQU sys_rseq, 398 @ restartable sequences 360 | -------------------------------------------------------------------------------- /Source Code/Chapter 7/upper.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ 10 | 11 | .global toupper @ Allow other files to call this routine 12 | 13 | toupper: PUSH {R4-R5} @ Save the registers we use. 14 | MOV R4, R1 15 | @ The loop is until byte pointed to by R1 is non-zero 16 | loop: LDRB R5, [R0], #1 @ load character and increment pointer 17 | @ If R5 > 'z' then goto cont 18 | CMP R5, #'z' @ is letter > 'z'? 19 | BGT cont 20 | @ Else if R5 < 'a' then goto end if 21 | CMP R5, #'a' 22 | BLT cont @ goto to end if 23 | @ if we got here then the letter is lower case, so convert it. 24 | SUB R5, #('a'-'A') 25 | cont: @ end if 26 | STRB R5, [R1], #1 @ store character to output str 27 | CMP R5, #0 @ stop on hitting a null character 28 | BNE loop @ loop if character isn't null 29 | SUB R0, R1, R4 @ get the length by subtracting the pointers 30 | POP {R4-R5} @ Restore the register we use. 31 | BX LR @ Return to caller 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/fileio.s: -------------------------------------------------------------------------------- 1 | @ Various macros to perform file I/O 2 | 3 | @ The fd parameter needs to be a register. 4 | @ Uses R0, R1, R7. 5 | @ Return code is in R0. 6 | 7 | .include "unistd.s" 8 | 9 | .equ O_RDONLY, 0 10 | .equ O_WRONLY, 1 11 | .equ O_CREAT, 0100 12 | .equ O_RDWR, 2 13 | .equ O_SYNC, 04010000 14 | .equ O_CLOEXEC, 02000000 15 | .equ S_RDWR, 0666 16 | 17 | .macro openFile fileName 18 | ldr r0, =\fileName 19 | ldr r1, =flags 20 | ldr r1, [r1] 21 | mov r2, #S_RDWR @ RW access rights 22 | mov r7, #sys_open 23 | svc 0 24 | .endm 25 | .macro readFile fd, buffer, length 26 | mov r0, \fd @ file descriptor 27 | ldr r1, =\buffer 28 | mov r2, #\length 29 | mov r7, #sys_read 30 | svc 0 31 | .endm 32 | .macro writeFile fd, buffer, length 33 | mov r0, \fd @ file descriptor 34 | ldr r1, =\buffer 35 | mov r2, \length 36 | mov r7, #sys_write 37 | svc 0 38 | .endm 39 | .macro flushClose fd 40 | @fsync syscall 41 | mov r0, \fd 42 | mov r7, #sys_fsync 43 | svc 0 44 | 45 | @close syscall 46 | mov r0, \fd 47 | mov r7, #sys_close 48 | svc 0 49 | .endm 50 | 51 | .data 52 | flags: .word O_RDWR+O_SYNC+O_CLOEXEC 53 | .text 54 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/gpiomacros.s: -------------------------------------------------------------------------------- 1 | @ Various macros to access the GPIO pins 2 | @ on the Raspberry Pi. 3 | @ 4 | @ R8 - file descriptor. 5 | @ 6 | 7 | .include "fileio.s" 8 | 9 | @ Macro nanoSleep to sleep .1 second 10 | @ Calls Linux nanosleep entry point which is function 162. 11 | @ Pass a reference to a timespec in both r0 and r1 12 | @ First is input time to sleep in seconds and nanoseconds. 13 | @ Second is time left to sleep if interrupted (which we ignore) 14 | .macro nanoSleep 15 | ldr r0, =timespecsec 16 | ldr r1, =timespecsec 17 | mov r7, #sys_nanosleep 18 | svc 0 19 | .endm 20 | .macro GPIOExport pin 21 | openFile gpioexp 22 | mov r8, r0 @ save the file descriptor 23 | writeFile r8, \pin, #2 24 | 25 | flushClose r8 26 | .endm 27 | .macro GPIODirectionOut pin 28 | @ copy pin into filename pattern 29 | ldr r1, =\pin 30 | ldr r2, =gpiopinfile 31 | add r2, #20 32 | ldrb r3, [r1], #1 @ load pin and post increment 33 | strb r3, [r2], #1 @ store to filename and post increment 34 | ldrb r3, [r1] 35 | strb r3, [r2] 36 | openFile gpiopinfile 37 | mov r8, r0 @ save the file descriptor 38 | writeFile r8, outstr, #3 39 | flushClose r8 40 | .endm 41 | .macro GPIOWrite pin, value 42 | @ copy pin into filename pattern 43 | ldr r1, =\pin 44 | ldr r2, =gpiovaluefile 45 | add r2, #20 46 | ldrb r3, [r1], #1 @ load pin and post increment 47 | strb r3, [r2], #1 @ store to filename and post increment 48 | ldrb r3, [r1] 49 | strb r3, [r2] 50 | openFile gpiovaluefile 51 | mov r8, r0 @ save the file descriptor 52 | writeFile r8, \value, #1 53 | flushClose r8 54 | .endm 55 | 56 | .data 57 | timespecsec: .word 0 58 | timespecnano: .word 100000000 59 | gpioexp: .asciz "/sys/class/gpio/export" 60 | gpiopinfile: .asciz "/sys/class/gpio/gpioxx/direction" 61 | gpiovaluefile: .asciz "/sys/class/gpio/gpioxx/value" 62 | outstr: .asciz "out" 63 | .align 2 @ save users of this file having to do this. 64 | .text 65 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/gpiomem.s: -------------------------------------------------------------------------------- 1 | @ Various macros to access the GPIO pins 2 | @ on the Raspberry Pi. 3 | @ 4 | @ R8 - memory map address. 5 | @ 6 | 7 | .include "fileio.s" 8 | 9 | .equ pagelen, 4096 10 | .equ setregoffset, 28 11 | .equ clrregoffset, 40 12 | .equ PROT_READ, 1 13 | .equ PROT_WRITE, 2 14 | .equ MAP_SHARED, 1 15 | 16 | @ Macro to map memory for GPIO Registers 17 | .macro mapMem 18 | openFile devmem @ open /dev/mem 19 | movs r4, r0 @ fd for memmap 20 | @ check for error and print error msg if necessary 21 | BPL 1f @ pos number file opened ok 22 | MOV R1, #1 @ stdout 23 | LDR R2, =memOpnsz @ Error msg 24 | LDR R2, [R2] 25 | writeFile R1, memOpnErr, R2 @ print the error 26 | B _end 27 | 28 | @ Setup can call the mmap2 Linux service 29 | 1: ldr r5, =gpioaddr @ address we want / 4096 30 | ldr r5, [r5] @ load the address 31 | mov r1, #pagelen @ size of mem we want 32 | mov r2, #(PROT_READ + PROT_WRITE) @ mem protection options 33 | mov r3, #MAP_SHARED @ mem share options 34 | mov r0, #0 @ let linux choose a virtual address 35 | mov r7, #sys_mmap2 @ mmap2 service num 36 | svc 0 @ call service 37 | movs r8, r0 @ keep the returned virtual address 38 | @ check for error and print error msg if necessary 39 | BPL 2f @ pos number file opened ok 40 | MOV R1, #1 @ stdout 41 | LDR R2, =memMapsz @ Error msg 42 | LDR R2, [R2] 43 | writeFile R1, memMapErr, R2 @ print the error 44 | B _end 45 | 2: 46 | .endm 47 | 48 | @ Macro nanoSleep to sleep .1 second 49 | @ Calls Linux nanosleep entry point which is function 162. 50 | @ Pass a reference to a timespec in both r0 and r1 51 | @ First is input time to sleep in seconds and nanoseconds. 52 | @ Second is time left to sleep if interrupted (which we ignore) 53 | .macro nanoSleep 54 | ldr r0, =timespecsec 55 | ldr r1, =timespecsec 56 | mov r7, #sys_nanosleep 57 | svc 0 58 | .endm 59 | .macro GPIODirectionOut pin 60 | ldr r2, =\pin @ offset of select register 61 | ldr r2, [r2] @ load the value 62 | ldr r1, [r8, r2] @ address of register 63 | ldr r3, =\pin @ address of pin table 64 | add r3, #4 @ load amount to shift from table 65 | ldr r3, [r3] @ load value of shift amt 66 | mov r0, #0b111 @ mask to clear 3 bits 67 | lsl r0, r3 @ shift into position 68 | bic r1, r0 @ clear the three bits 69 | mov r0, #1 @ 1 bit to shift into pos 70 | lsl r0, r3 @ shift by amount from table 71 | orr r1, r0 @ set the bit 72 | str r1, [r8, r2] @ save it to register to do work 73 | .endm 74 | .macro GPIOTurnOn pin, value 75 | mov r2, r8 @ address of gpio regs 76 | add r2, #setregoffset @ off to set reg 77 | mov r0, #1 @ 1 bit to shift into pos 78 | ldr r3, =\pin @ base of pin info table 79 | add r3, #8 @ add offset for shift amt 80 | ldr r3, [r3] @ load shift from table 81 | lsl r0, r3 @ do the shift 82 | str r0, [r2] @ write to the register 83 | .endm 84 | .macro GPIOTurnOff pin, value 85 | mov r2, r8 @ address of gpio regs 86 | add r2, #clrregoffset @ off set of clr reg 87 | mov r0, #1 @ 1 bit to shift into pos 88 | ldr r3, =\pin @ base of pin info table 89 | add r3, #8 @ add offset for shift amt 90 | ldr r3, [r3] @ load shift from table 91 | lsl r0, r3 @ do the shift 92 | str r0, [r2] @ write to the register 93 | .endm 94 | 95 | .data 96 | timespecsec: .word 0 97 | timespecnano: .word 100000000 98 | devmem: .asciz "/dev/mem" 99 | memOpnErr: .asciz "Failed to open /dev/mem\n" 100 | memOpnsz: .word .-memOpnErr 101 | memMapErr: .asciz "Failed to map memory\n" 102 | memMapsz: .word .-memMapErr 103 | .align 4 @ relign after strings 104 | gpioaddr: .word 0x3F200 @ mem address of gpio register / 4096 105 | pin17: .word 4 @ offset to select register 106 | .word 21 @ bit offset in select register 107 | .word 17 @ bit offset in set & clr register 108 | pin22: .word 8 @ offset to select register 109 | .word 6 @ bit offset in select register 110 | .word 22 @ bit offset in set & clr register 111 | pin27: .word 8 @ offset to select register 112 | .word 21 @ bit offset in select register 113 | .word 27 @ bit offset in set & clr register 114 | 115 | .text 116 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/main.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to flash three LEDs connnected to the 3 | @ Raspberry Pi GPIO port. 4 | @ 5 | @ r6 - loop variable to flash lights 10 times 6 | @ 7 | .include "gpiomacros.s" 8 | 9 | .global _start @ Provide program starting address to linker 10 | _start: GPIOExport pin17 11 | GPIOExport pin27 12 | GPIOExport pin22 13 | nanoSleep 14 | 15 | GPIODirectionOut pin17 16 | GPIODirectionOut pin27 17 | GPIODirectionOut pin22 18 | @ setup a loop counter for 10 iterations 19 | mov r6, #10 20 | 21 | loop: GPIOWrite pin17, high 22 | nanoSleep 23 | GPIOWrite pin17, low 24 | GPIOWrite pin27, high 25 | nanoSleep 26 | GPIOWrite pin27, low 27 | GPIOWrite pin22, high 28 | nanoSleep 29 | GPIOWrite pin22, low 30 | @decrement loop counter and see if we loop 31 | subs r6, #1 @ Subtract 1 from loop register setting status register 32 | bne loop @ If we haven't counted down to 0 then loop 33 | 34 | _end: mov R0, #0 @ Use 0 return code 35 | mov R7, #1 @ Service command code 1 terminates this program 36 | svc 0 @ Linus command to terminate program 37 | 38 | pin17: .asciz "17" 39 | pin27: .asciz "27" 40 | pin22: .asciz "22" 41 | low: .asciz "0" 42 | high: .asciz "1" 43 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/mainmem.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to flash three LEDs connnected to the 3 | @ Raspberry Pi GPIO port using direct memory access. 4 | @ 5 | @ r6 - loop variable to flash lights 10 times 6 | @ 7 | .include "gpiomem.s" 8 | 9 | .global _start @ Provide program starting address to linker 10 | _start: mapMem 11 | nanoSleep 12 | 13 | GPIODirectionOut pin17 14 | GPIODirectionOut pin27 15 | GPIODirectionOut pin22 16 | @ setup a loop counter for 10 iterations 17 | mov r6, #10 18 | 19 | loop: GPIOTurnOn pin17 20 | nanoSleep 21 | GPIOTurnOff pin17 22 | GPIOTurnOn pin27 23 | nanoSleep 24 | GPIOTurnOff pin27 25 | GPIOTurnOn pin22 26 | nanoSleep 27 | brk1: 28 | GPIOTurnOff pin22 29 | @decrement loop counter and see if we loop 30 | subs r6, #1 @ Subtract 1 from loop register setting status register 31 | bne loop @ If we haven't counted down to 0 then loop 32 | 33 | _end: mov R0, #0 @ Use 0 return code 34 | mov R7, #1 @ Service command code 1 terminates this program 35 | svc 0 @ Linus command to terminate program 36 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/makefile: -------------------------------------------------------------------------------- 1 | FLASHOBJS = main.o 2 | FLASHMEMOBJS = mainmem.o 3 | 4 | ifdef DEBUG 5 | DEBUGFLGS = -g 6 | else 7 | DEBUGFLGS = 8 | endif 9 | LSTFLGS = 10 | 11 | all: flash flashmem 12 | 13 | %.o : %.s 14 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 15 | 16 | flash: $(FLASHOBJS) 17 | ld -o flash $(FLASHOBJS) 18 | 19 | flashmem: $(FLASHMEMOBJS) 20 | ld -o flashmem $(FLASHMEMOBJS) 21 | -------------------------------------------------------------------------------- /Source Code/Chapter 8/unistd.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Defines for the Linux system calls. 3 | @ This list is from Raspbian Buster 4 | @ 5 | 6 | .EQU sys_restart_syscall, 0 @ restart a system call after interruption by a stop signal 7 | .EQU sys_exit, 1 @ cause normal process termination 8 | .EQU sys_fork, 2 @ create a child process 9 | .EQU sys_read, 3 @ read from a file descriptor 10 | .EQU sys_write, 4 @ write to a file descriptor 11 | .EQU sys_open, 5 @ open and possibly create a file 12 | .EQU sys_close, 6 @ close a file descriptor 13 | .EQU sys_creat, 8 @ create a new file or rewrite an existing one 14 | .EQU sys_link, 9 @ make a new name for a file 15 | .EQU sys_unlink, 10 @ delete a name and possibly the file it refers to 16 | .EQU sys_execve, 11 @ execute program 17 | .EQU sys_chdir, 12 @ change working directory 18 | .EQU sys_mknod, 14 @ create a special or ordinary file 19 | .EQU sys_chmod, 15 @ change file mode bits 20 | .EQU sys_lchown, 16 @ change the owner and group of a symbolic link 21 | .EQU sys_lseek, 19 @ reposition read/write file offset 22 | .EQU sys_getpid, 20 @ get process identification 23 | .EQU sys_mount, 21 @ mount filesystem 24 | .EQU sys_setuid, 23 @ set user identity 25 | .EQU sys_getuid, 24 @ get user identity 26 | .EQU sys_ptrace, 26 @ process trace 27 | .EQU sys_pause, 29 @ wait for signal 28 | .EQU sys_access, 33 @ check user's permissions for a file 29 | .EQU sys_nice, 34 @ change process priority 30 | .EQU sys_sync, 36 @ commit filesystem caches to disk 31 | .EQU sys_kill, 37 @ send signal to a process 32 | .EQU sys_rename, 38 @ change the name or location of a file 33 | .EQU sys_mkdir, 39 @ create a directory 34 | .EQU sys_rmdir, 40 @ delete a directory 35 | .EQU sys_dup, 41 @ duplicate a file descriptor 36 | .EQU sys_pipe, 42 @ create pipe 37 | .EQU sys_times, 43 @ get process times 38 | .EQU sys_brk, 45 @ change data segment size 39 | .EQU sys_setgid, 46 @ set group identity 40 | .EQU sys_getgid, 47 @ get group identity 41 | .EQU sys_geteuid, 49 @ get user identity 42 | .EQU sys_getegid, 50 @ get group identity 43 | .EQU sys_acct, 51 @ switch process accounting on or off 44 | .EQU sys_umount2, 52 @ unmount filesystem 45 | .EQU sys_ioctl, 54 @ control device 46 | .EQU sys_fcntl, 55 @ manipulate file descriptor 47 | .EQU sys_setpgid, 57 @ set process group 48 | .EQU sys_umask, 60 @ set file mode creation mask 49 | .EQU sys_chroot, 61 @ change root directory 50 | .EQU sys_ustat, 62 @ get filesystem statistics 51 | .EQU sys_dup2, 63 @ duplicate a file descriptor 52 | .EQU sys_getppid, 64 @ get the parent process ID 53 | .EQU sys_getpgrp, 65 @ get process group 54 | .EQU sys_setsid, 66 @ creates a session and sets the process group ID 55 | .EQU sys_sigaction, 67 @ examine and change a signal action 56 | .EQU sys_setreuid, 70 @ set real and/or effective user ID 57 | .EQU sys_setregid, 71 @ set real and/or effective group ID 58 | .EQU sys_sigsuspend, 72 @ wait for a signal 59 | .EQU sys_sigpending, 73 @ examine pending signals 60 | .EQU sys_sethostname, 74 @ set hostname 61 | .EQU sys_setrlimit, 75 @ control maximum resource consumption 62 | .EQU sys_getrusage, 77 @ get resource usage 63 | .EQU sys_gettimeofday, 78 @ get time 64 | .EQU sys_settimeofday, 79 @ set time 65 | .EQU sys_getgroups, 80 @ get list of supplementary group IDs 66 | .EQU sys_setgroups, 81 @ set list of supplementary group IDs 67 | .EQU sys_symlink, 83 @ make a new name for a file 68 | .EQU sys_readlink, 85 @ read value of a symbolic link 69 | .EQU sys_uselib, 86 @load shared library 70 | .EQU sys_swapon, 87 @ start swapping to file/device 71 | .EQU sys_reboot, 88 @ reboot 72 | .EQU sys_munmap, 91 @ unmap files or devices into memory 73 | .EQU sys_truncate, 92 @ truncate a file to a specified length 74 | .EQU sys_ftruncate, 93 @ truncate a file to a specified length 75 | .EQU sys_fchmod, 94 @ change permissions of a file 76 | .EQU sys_fchown, 95 @ change ownership of a file 77 | .EQU sys_getpriority, 96 @ get program scheduling priority 78 | .EQU sys_setpriority, 97 @ set program scheduling priority 79 | .EQU sys_statfs, 99 @ get filesystem statistics 80 | .EQU sys_fstatfs, 100 @ get filesystem statistics 81 | .EQU sys_syslog, 103 @ read and/or clear kernel message ring buffer; set console_loglevel 82 | .EQU sys_setitimer, 104 @ set value of an interval timer 83 | .EQU sys_getitimer, 105 @ get value of an interval timer 84 | .EQU sys_stat, 106 @ get file status 85 | .EQU sys_lstat, 107 @ get file status 86 | .EQU sys_fstat, 108 @ get file status 87 | .EQU sys_vhangup, 111 @ virtually hangup the current terminal 88 | .EQU sys_wait4, 114 @ wait for process to change state, BSD style 89 | .EQU sys_swapoff, 115 @ stop swapping to file/device 90 | .EQU sys_sysinfo, 116 @ return system information 91 | .EQU sys_fsync, 118 @ synchronize a file's in-core state with storage 92 | .EQU sys_sigreturn, 119 @ return from signal handler and cleanup stack frame 93 | .EQU sys_clone, 120 @ create a child process 94 | .EQU sys_setdomainname, 121 @ set NIS domain name 95 | .EQU sys_uname, 122 @ get name and information about current kernel 96 | .EQU sys_adjtimex, 124 @ tune kernel clock 97 | .EQU sys_mprotect, 125 @ set protection on a region of memory 98 | .EQU sys_sigprocmask, 126 @ examine and change blocked signals 99 | .EQU sys_init_module, 128 @ load a kernel module 100 | .EQU sys_delete_module, 129 @ unload a kernel module 101 | .EQU sys_quotactl, 131 @ manipulate disk quotas 102 | .EQU sys_getpgid, 132 @ get process group 103 | .EQU sys_fchdir, 133 @ change working directory 104 | .EQU sys_bdflush, 134 @ start, flush, or tune buffer-dirty-flush daemon 105 | .EQU sys_sysfs, 135 @ get filesystem type information 106 | .EQU sys_personality, 136 @ set the process execution domain 107 | .EQU sys_setfsuid, 138 @ set user identity used for filesystem checks 108 | .EQU sys_setfsgid, 139 @ set group identity used for filesystem checks 109 | .EQU sys__llseek, 140 @ reposition read/write file offset 110 | .EQU sys_getdents, 141 @ get directory entries 111 | .EQU sys__newselect, 142 @ synchronous I/O multiplexing 112 | .EQU sys_flock, 143 @ apply or remove an advisory lock on an open file 113 | .EQU sys_msync, 144 @ synchronize a file with a memory map 114 | .EQU sys_readv, 145 @ read data into multiple buffers 115 | .EQU sys_writev, 146 @ write data into multiple buffers 116 | .EQU sys_getsid, 147 @ get session ID 117 | .EQU sys_fdatasync, 148 @ synchronize a file's in-core state with storage device 118 | .EQU sys__sysctl, 149 @ read/write system parameters 119 | .EQU sys_mlock, 150 @ lock memory 120 | .EQU sys_munlock, 151 @ unlock memory 121 | .EQU sys_mlockall, 152 @ lock memory 122 | .EQU sys_munlockall, 153 @ unlock memory 123 | .EQU sys_sched_setparam, 154 @ set scheduling parameters 124 | .EQU sys_sched_getparam, 155 @ get scheduling parameters 125 | .EQU sys_sched_setscheduler, 156 @ set and get scheduling policy/parameters 126 | .EQU sys_sched_getscheduler, 157 @ set and get scheduling policy/parameters 127 | .EQU sys_sched_yield, 158 @ yield the processor 128 | .EQU sys_sched_get_priority_max, 159 @ get static priority max 129 | .EQU sys_sched_get_priority_min, 160 @ get static priority min 130 | .EQU sys_sched_rr_get_interval, 161 @ get the SCHED_RR interval for the named process 131 | .EQU sys_nanosleep, 162 @ high-resolution sleep 132 | .EQU sys_mremap, 163 @ remap a virtual memory address 133 | .EQU sys_setresuid, 164 @ set real, effective and saved user ID 134 | .EQU sys_getresuid, 165 @ get real, effective and saved user ID 135 | .EQU sys_poll, 168 @ wait for some event on a file descriptor 136 | .EQU sys_nfsservctl, 169 @ syscall interface to kernel nfs daemon 137 | .EQU sys_setresgid, 170 @ set real, effective and saved group ID 138 | .EQU sys_getresgid, 171 @ get real, effective and saved group ID 139 | .EQU sys_prctl, 172 @ operations on a process 140 | .EQU sys_rt_sigreturn, 173 @ return from signal handler and cleanup stack frame 141 | .EQU sys_rt_sigaction, 174 @ examine and change a signal action 142 | .EQU sys_rt_sigprocmask, 175 @ examine and change blocked signals 143 | .EQU sys_rt_sigpending, 176 @ examine pending signals 144 | .EQU sys_rt_sigtimedwait, 177 @ synchronously wait for queued signals 145 | .EQU sys_rt_sigqueueinfo, 178 @ queue a signal and data 146 | .EQU sys_rt_sigsuspend, 179 @ wait for a signal 147 | .EQU sys_pread64, 180 @ read from a file descriptor at a given offset 148 | .EQU sys_pwrite64, 181 @ write to a file descriptor at a given offset 149 | .EQU sys_chown, 182 @ change ownership of a file 150 | .EQU sys_getcwd, 183 @ get current working directory 151 | .EQU sys_capget, 184 @ get capabilities of thread(s) 152 | .EQU sys_capset, 185 @ set capabilities of thread(s) 153 | .EQU sys_sigaltstack, 186 @ set and/or get signal stack context 154 | .EQU sys_sendfile, 187 @ transfer data between file descriptors 155 | .EQU sys_vfork, 190 @ create a child process and block parent 156 | .EQU sys_ugetrlimit, 191 @ get resource limits 157 | .EQU sys_mmap2, 192 @ map files or devices into memory 158 | .EQU sys_truncate64, 193 @ truncate a file to a specified length 159 | .EQU sys_ftruncate64, 194 @ truncate a file to a specified length 160 | .EQU sys_stat64, 195 @ get file status 161 | .EQU sys_lstat64, 196 @ get file status 162 | .EQU sys_fstat64, 197 @ get file status 163 | .EQU sys_lchown32, 198 @ change ownership of a file 164 | .EQU sys_getuid32, 199 @ get user identity 165 | .EQU sys_getgid32, 200 @ get group identity 166 | .EQU sys_geteuid32, 201 @ get user identity 167 | .EQU sys_getegid32, 202 @ get group identity 168 | .EQU sys_setreuid32, 203 @ set real and/or effective user ID 169 | .EQU sys_setregid32, 204 @ set real and/or effective group ID 170 | .EQU sys_getgroups32, 205 @ get list of supplementary group IDs 171 | .EQU sys_setgroups32, 206 @ set list of supplementary group IDs 172 | .EQU sys_fchown32, 207 @ change ownership of a file 173 | .EQU sys_setresuid32, 208 @ set real, effective and saved user ID 174 | .EQU sys_getresuid32, 209 @ get real, effective and saved user ID 175 | .EQU sys_setresgid32, 210 @ set real, effective and saved group ID 176 | .EQU sys_getresgid32, 211 @ get real, effective and saved group ID 177 | .EQU sys_chown32, 212 @ change ownership of a file 178 | .EQU sys_setuid32, 213 @ set user identity 179 | .EQU sys_setgid32, 214 @ set group identity 180 | .EQU sys_setfsuid32, 215 @ set user identity used for filesystem checks 181 | .EQU sys_setfsgid32, 216 @ set group identity used for filesystem checks 182 | .EQU sys_getdents64, 217 @ get directory entries 183 | .EQU sys_pivot_root, 218 @ change the root filesystem 184 | .EQU sys_mincore, 219 @ determine whether pages are resident in memory 185 | .EQU sys_madvise, 220 @ give advice about use of memory 186 | .EQU sys_fcntl64, 221 @ manipulate file descriptor 187 | .EQU sys_gettid, 224 @ get thread identification 188 | .EQU sys_readahead, 225 @ initiate file readahead into page cache 189 | .EQU sys_setxattr, 226 @ set an extended attribute value 190 | .EQU sys_lsetxattr, 227 @ set an extended attribute value 191 | .EQU sys_fsetxattr, 228 @ set an extended attribute value 192 | .EQU sys_getxattr, 229 @ retrieve an extended attribute value 193 | .EQU sys_lgetxattr, 230 @ retrieve an extended attribute value 194 | .EQU sys_fgetxattr, 231 @ retrieve an extended attribute value 195 | .EQU sys_listxattr, 232 @ list extended attribute names 196 | .EQU sys_llistxattr, 233 @ list extended attribute names 197 | .EQU sys_flistxattr, 234 @ list extended attribute names 198 | .EQU sys_removexattr, 235 @ remove an extended attribute 199 | .EQU sys_lremovexattr, 236 @ remove an extended attribute 200 | .EQU sys_fremovexattr, 237 @ remove an extended attribute 201 | .EQU sys_tkill, 238 @ send a signal to a thread 202 | .EQU sys_sendfile64, 239 @ transfer data between file descriptors 203 | .EQU sys_futex, 240 @ fast user-space locking 204 | .EQU sys_sched_setaffinity, 241 @ set a thread's CPU affinity mask 205 | .EQU sys_sched_getaffinity, 242 @ get a thread's CPU affinity mask 206 | .EQU sys_io_setup, 243 @ create an asynchronous I/O context 207 | .EQU sys_io_destroy, 244 @ destroy an asynchronous I/O context 208 | .EQU sys_io_getevents, 245 @ read asynchronous I/O events from the completion queue 209 | .EQU sys_io_submit, 246 @ submit asynchronous I/O blocks for processing 210 | .EQU sys_io_cancel, 247 @ cancel an outstanding asynchronous I/O operation 211 | .EQU sys_exit_group, 248 @ exit all threads in a process 212 | .EQU sys_lookup_dcookie, 249 @ return a directory entry's path 213 | .EQU sys_epoll_create, 250 @ open an epoll file descriptor 214 | .EQU sys_epoll_ctl, 251 @ control interface for an epoll file descriptor 215 | .EQU sys_epoll_wait, 252 @ wait for an I/O event on an epoll file descriptor 216 | .EQU sys_remap_file_pages, 253 @ create a nonlinear file mapping 217 | .EQU sys_set_tid_address, 256 @ set pointer to thread ID 218 | .EQU sys_timer_create, 257 @ create a POSIX per-process timer 219 | .EQU sys_timer_settime, 258 @arm/disarm state of POSIX per-process timer 220 | .EQU sys_timer_gettime, 259 @ fetch state of POSIX per-process timer 221 | .EQU sys_timer_getoverrun, 260 @ get overrun count for a POSIX per-process timer 222 | .EQU sys_timer_delete, 261 @ delete a POSIX per-process timer 223 | .EQU sys_clock_settime, 262 @ clock and timer functions 224 | .EQU sys_clock_gettime, 263 @ clock and timer functions 225 | .EQU sys_clock_getres, 264 @ clock and timer functions 226 | .EQU sys_clock_nanosleep, 265 @ high-resolution sleep with specifiable clock 227 | .EQU sys_statfs64, 266 @ get filesystem statistics 228 | .EQU sys_fstatfs64, 267 @ get filesystem statistics 229 | .EQU sys_tgkill, 268 @ send a signal to a thread 230 | .EQU sys_utimes, 269 @ change file last access and modification times 231 | .EQU sys_arm_fadvise64_64, 270 @ predeclare an access pattern for file data 232 | .EQU sys_pciconfig_iobase, 271 @ pci device information handling 233 | .EQU sys_pciconfig_read, 272 @ pci device information handling 234 | .EQU sys_pciconfig_write, 273 @ pci device information handling 235 | .EQU sys_mq_open, 274 @ open a message queue 236 | .EQU sys_mq_unlink, 275 @ remove a message queue 237 | .EQU sys_mq_timedsend, 276 @ send a message to a message queue 238 | .EQU sys_mq_timedreceive, 277 @ receive a message from a message queue 239 | .EQU sys_mq_notify, 278 @ register for notification when a message is available 240 | .EQU sys_mq_getsetattr, 279 @ get/set message queue attributes 241 | .EQU sys_waitid, 280 @ wait for a child process to change state 242 | .EQU sys_socket, 281 @ create an endpoint for communication 243 | .EQU sys_bind, 282 @ bind a name to a socket 244 | .EQU sys_connect, 283 @ initiate a connection on a socket 245 | .EQU sys_listen, 284 @ listen for connections on a socket 246 | .EQU sys_accept, 285 @ accept a connection on a socket 247 | .EQU sys_getsockname, 286 @ get socket name 248 | .EQU sys_getpeername, 287 @ get name of connected peer socket 249 | .EQU sys_socketpair, 288 @ create a pair of connected sockets 250 | .EQU sys_send, 289 @ send a message on a socket 251 | .EQU sys_sendto, 290 @ send a message on a socket 252 | .EQU sys_recv, 291 @ receive a message from a socket 253 | .EQU sys_recvfrom, 292 @ receive a message from a socket 254 | .EQU sys_shutdown, 293 @ shut down part of a full-duplex connection 255 | .EQU sys_setsockopt, 294 @ set options on sockets 256 | .EQU sys_getsockopt, 295 @ get options on sockets 257 | .EQU sys_sendmsg, 296 @ send a message on a socket using a message structure 258 | .EQU sys_recvmsg, 297 @ receive a message from a socket 259 | .EQU sys_semop, 298 @ System V semaphore operations 260 | .EQU sys_semget, 299 @ get a System V semaphore set identifier 261 | .EQU sys_semctl, 300 @ System V semaphore control operations 262 | .EQU sys_msgsnd, 301 @ XSI message send operation 263 | .EQU sys_msgrcv, 302 @ XSI message receive operation 264 | .EQU sys_msgget, 303 @ get a System V message queue identifier 265 | .EQU sys_msgctl, 304 @ System V message control operations 266 | .EQU sys_shmat, 305 @ XSI shared memory attach operation 267 | .EQU sys_shmdt, 306 @ XSI shared memory detach operation 268 | .EQU sys_shmget, 307 @ allocates a System V shared memory segment 269 | .EQU sys_shmctl, 308 @ System V shared memory control 270 | .EQU sys_add_key, 309 @ add a key to the kernel's key management facility 271 | .EQU sys_request_key, 310 @ request a key from the kernel's key management facility 272 | .EQU sys_keyctl, 311 @ manipulate the kernel's key management facility 273 | .EQU sys_semtimedop, 312 @ System V semaphore operations 274 | .EQU sys_vserver, 313 @ Unimplemented 275 | .EQU sys_ioprio_set, 314 @ set I/O scheduling class and priority 276 | .EQU sys_ioprio_get, 315 @ get I/O scheduling class and priority 277 | .EQU sys_inotify_init, 316 @ initialize an inotify instance 278 | .EQU sys_inotify_add_watch, 317 @ add a watch to an initialized inotify instance 279 | .EQU sys_inotify_rm_watch, 318 @ remove an existing watch from an inotify instance 280 | .EQU sys_mbind, 319 @ set memory policy for a memory range 281 | .EQU sys_get_mempolicy, 320 @ retrieve NUMA memory policy for a thread 282 | .EQU sys_set_mempolicy, 321 @ set default NUMA memory policy for a thread and its children 283 | .EQU sys_openat, 322 @ open file relative to directory file descriptor 284 | .EQU sys_mkdirat, 323 @ create a directory 285 | .EQU sys_mknodat, 324 @ create a special or ordinary file 286 | .EQU sys_fchownat, 325 @ change owner and group of a file relative to directory file descriptor 287 | .EQU sys_futimesat, 326 @ change timestamps of a file relative to a directory file descriptor 288 | .EQU sys_fstatat64, 327 @ get file status 289 | .EQU sys_unlinkat, 328 @ delete a name and possibly the file it refers to 290 | .EQU sys_renameat, 329 @ change the name or location of a file 291 | .EQU sys_linkat, 330 @ make a new name for a file 292 | .EQU sys_symlinkat, 331 @ make a new name for a file 293 | .EQU sys_readlinkat, 332 @ read value of a symbolic link 294 | .EQU sys_fchmodat, 333 @ change permissions of a file 295 | .EQU sys_faccessat, 334 @ determine accessibility of a file relative to directory file descriptor 296 | .EQU sys_pselect6, 335 @ synchronous I/O multiplexing 297 | .EQU sys_ppoll, 336 @ wait for some event on a file descriptor 298 | .EQU sys_unshare, 337 @ run program with some namespaces unshared from parent 299 | .EQU sys_set_robust_list, 338 @ set list of robust futexes 300 | .EQU sys_get_robust_list, 339 @ get list of robust futexes 301 | .EQU sys_splice, 340 @ splice data to/from a pipe 302 | .EQU sys_arm_sync_file_range, 341 @ sync a file segment with disk 303 | .EQU sys_tee, 342 @ duplicating pipe content 304 | .EQU sys_vmsplice, 343 @ splice user pages to/from a pipe 305 | .EQU sys_move_pages, 344 @ move individual pages of a process to another node 306 | .EQU sys_getcpu, 345 @ determine CPU and NUMA node on which the calling thread is running 307 | .EQU sys_epoll_pwait, 346 @ wait for an I/O event on an epoll file descriptor 308 | .EQU sys_kexec_load, 347 @ load a new kernel for later execution 309 | .EQU sys_utimensat, 348 @ change file timestamps with nanosecond precision 310 | .EQU sys_signalfd, 349 @ create a file descriptor for accepting signals 311 | .EQU sys_timerfd_create, 350 @ timers that notify via file descriptors 312 | .EQU sys_eventfd, 351 @ create a file descriptor for event notification 313 | .EQU sys_fallocate, 352 @ manipulate file space 314 | .EQU sys_timerfd_settime, 353 @ timers that notify via file descriptors 315 | .EQU sys_timerfd_gettime, 354 @ timers that notify via file descriptors 316 | .EQU sys_signalfd4, 355 @ create a file descriptor for accepting signals 317 | .EQU sys_eventfd2, 356 @ create a file descriptor for event notification 318 | .EQU sys_epoll_create1, 357 @ open an epoll file descriptor 319 | .EQU sys_dup3, 358 @ duplicate a file descriptor 320 | .EQU sys_pipe2, 359 @ create pipe 321 | .EQU sys_inotify_init1, 360 @ initialize an inotify instance 322 | .EQU sys_preadv, 361 @ read data into multiple buffers 323 | .EQU sys_pwritev, 362 @ write data into multiple buffers 324 | .EQU sys_rt_tgsigqueueinfo, 363 @ queue a signal and data 325 | .EQU sys_perf_event_open, 364 @ set up performance monitoring 326 | .EQU sys_recvmmsg, 365 @ receive multiple messages on a socket 327 | .EQU sys_accept4, 366 @ accept a connection on a socket 328 | .EQU sys_fanotify_init, 367 @ create and initialize fanotify group 329 | .EQU sys_fanotify_mark, 368 @ add, remove, or modify an fanotify mark on a filesystem object 330 | .EQU sys_prlimit64, 369 @ get/set resource limits 331 | .EQU sys_name_to_handle_at, 370 @ obtain handle for a pathname 332 | .EQU sys_open_by_handle_at, 371 @ open file via a handle 333 | .EQU sys_clock_adjtime, 372 @ tune kernel clock 334 | .EQU sys_syncfs, 373 @ commit filesystem caches to disk 335 | .EQU sys_sendmmsg, 374 @ send multiple messages on a socket 336 | .EQU sys_setns, 375 @ reassociate thread with a namespace 337 | .EQU sys_process_vm_readv, 376 @ transfer data between process address spaces 338 | .EQU sys_process_vm_writev, 377 @ transfer data between process address spaces 339 | .EQU sys_kcmp, 378 @ compare two processes to determine if they share a kernel resource 340 | .EQU sys_finit_module, 379 @ load a kernel module 341 | .EQU sys_sched_setattr, 380 @ set scheduling policy and attributes 342 | .EQU sys_sched_getattr, 381 @ get scheduling policy and attributes 343 | .EQU sys_renameat2, 382 @ change the name or location of a file 344 | .EQU sys_seccomp, 383 @ operate on Secure Computing state of the process 345 | .EQU sys_getrandom, 384 @ obtain a series of random bytes 346 | .EQU sys_memfd_create, 385 @ create an anonymous file 347 | .EQU sys_bpf, 386 @ perform a command on an extended BPF map or program 348 | .EQU sys_execveat, 387 @ execute program relative to a directory file descriptor 349 | .EQU sys_userfaultfd, 388 @ create a file descriptor for handling page faults in user space 350 | .EQU sys_membarrier, 389 @ issue memory barriers on a set of threads 351 | .EQU sys_mlock2, 390 @ lock memory 352 | .EQU sys_copy_file_range, 391 @ Copy a range of data from one file to another 353 | .EQU sys_preadv2, 392 @ read data into multiple buffers 354 | .EQU sys_pwritev2, 393 @ write data into multiple buffers 355 | .EQU sys_pkey_mprotect, 394 @ set protection on a region of memory 356 | .EQU sys_pkey_alloc, 395 @ allocate a protection key 357 | .EQU sys_pkey_free, 396 @ free a protection key 358 | .EQU sys_statx, 397 @ get file status (extended) 359 | .EQU sys_rseq, 398 @ restartable sequences 360 | -------------------------------------------------------------------------------- /Source Code/Chapter 9/addexamp2.s: -------------------------------------------------------------------------------- 1 | 2 | @ 3 | @ Example of 64-Bit addition with the ADD/ADC instructions. 4 | @ 5 | 6 | .include "debug.s" 7 | 8 | .global main @ Provide program starting address to linker 9 | 10 | @ Load the registers with some data 11 | @ First 64-bit number is 0x00000003FFFFFFFF 12 | main: 13 | push {R4-R12, LR} 14 | MOV R2, #0x00000003 15 | MOV R3, #0xFFFFFFFF @Assembler will change to MVN 16 | @ Second 64-bit number is 0x0000000500000001 17 | MOV R4, #0x00000005 18 | MOV R5, #0x00000001 19 | 20 | printStr "Inputs:" 21 | printReg 2 22 | printReg 3 23 | printReg 4 24 | printReg 5 25 | ADDS R1, R3, R5 @ Lower order word 26 | ADC R0, R2, R4 @ Higher order word 27 | 28 | printStr "Outputs:" 29 | printReg 1 30 | printReg 0 31 | mov r0, #0 @ return code 32 | pop {R4-R12, PC} 33 | 34 | -------------------------------------------------------------------------------- /Source Code/Chapter 9/debug.s: -------------------------------------------------------------------------------- 1 | @ Various macros to help with debugging 2 | 3 | @ These macros preseve all registers. 4 | @ Beware they will change cpsr. 5 | 6 | .macro printReg reg 7 | push {r0-r4, lr} @ save regs 8 | mov r2, R\reg @ for the %d 9 | mov r3, R\reg @ for the %x 10 | mov r1, #\reg 11 | add r1, #'0' @ for %c 12 | ldr r0, =ptfStr @ printf format str 13 | bl printf @ call printf 14 | pop {r0-r4, lr} @ restore regs 15 | .endm 16 | 17 | .macro printStr str 18 | push {r0-r4, lr} @ save regs 19 | ldr r0, =1f @ load print str 20 | bl printf @ call printf 21 | pop {r0-r4, lr} @ restore regs 22 | b 2f @ branch around str 23 | 1: .asciz "\str\n" 24 | .align 4 25 | 2: 26 | .endm 27 | 28 | .data 29 | ptfStr: .asciz "R%c = %16d, 0x%08x\n" 30 | .align 4 31 | .text 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 9/makefile: -------------------------------------------------------------------------------- 1 | LIBOBJS = upper.o 2 | 3 | ifdef DEBUG 4 | DEBUGFLGS = -g 5 | else 6 | DEBUGFLGS = 7 | endif 8 | LSTFLGS = 9 | 10 | all: addexamp2 uppertst uppertst2 uppertst3 uppertst4 11 | 12 | %.o : %.s 13 | as $(DEBUGFLGS) $(LSTFLGS) $< -o $@ 14 | 15 | addexamp2: addexamp2.s debug.s 16 | gcc -o addexamp2 addexamp2.s 17 | 18 | uppertst: uppertst.c upper.s 19 | gcc -o uppertst uppertst.c upper.s 20 | 21 | libupper.a: $(LIBOBJS) 22 | ar -cvq libupper.a upper.o 23 | 24 | uppertst2: uppertst.c libupper.a 25 | gcc -o uppertst2 uppertst.c libupper.a 26 | 27 | libup.so.1.0: $(LIBOBJS) 28 | gcc -shared -Wl,-soname,libup.so.1 -o libup.so.1.0 $(LIBOBJS) 29 | mv libup.so.1.0 /usr/local/lib 30 | ln -sf /usr/local/lib/libup.so.1.0 /usr/local/lib/libup.so.1 31 | ln -sf /usr/local/lib/libup.so.1.0 /usr/local/lib/libup.so 32 | 33 | uppertst3: libup.so.1.0 34 | gcc -o uppertst3 -lup uppertst.c 35 | 36 | uppertst4: uppertst4.c 37 | gcc -o uppertst4 uppertst4.c -------------------------------------------------------------------------------- /Source Code/Chapter 9/upper.s: -------------------------------------------------------------------------------- 1 | @ 2 | @ Assembler program to convert a string to 3 | @ all upper case. 4 | @ 5 | @ R1 - address of output string 6 | @ R0 - address of input string 7 | @ R4 - original output string for length calc. 8 | @ R5 - current character being processed 9 | @ 10 | 11 | .global mytoupper @ Allow other files to call this routine 12 | 13 | mytoupper: PUSH {R4-R5} @ Save the registers we use. 14 | MOV R4, R1 15 | @ The loop is until byte pointed to by R1 is non-zero 16 | loop: LDRB R5, [R0], #1 @ load character and increment pointer 17 | @ If R5 > 'z' then goto cont 18 | CMP R5, #'z' @ is letter > 'z'? 19 | BGT cont 20 | @ Else if R5 < 'a' then goto end if 21 | CMP R5, #'a' 22 | BLT cont @ goto to end if 23 | @ if we got here then the letter is lower case, so convert it. 24 | SUB R5, #('a'-'A') 25 | cont: @ end if 26 | STRB R5, [R1], #1 @ store character to output str 27 | CMP R5, #0 @ stop on hitting a null character 28 | BNE loop @ loop if character isn't null 29 | SUB R0, R1, R4 @ get the length by subtracting the pointers 30 | POP {R4-R5} @ Restore the register we use. 31 | BX LR @ Return to caller 32 | -------------------------------------------------------------------------------- /Source Code/Chapter 9/uppertst.c: -------------------------------------------------------------------------------- 1 | // 2 | // C program to call our Assembly 3 | // toupper routine. 4 | // 5 | 6 | #include 7 | 8 | extern int mytoupper( char *, char * ); 9 | 10 | #define MAX_BUFFSIZE 255 11 | int main() 12 | { 13 | char *str = "This is a test."; 14 | char outBuf[MAX_BUFFSIZE]; 15 | int len; 16 | 17 | len = mytoupper( str, outBuf ); 18 | printf("Before str: %s\n", str); 19 | printf("After str: %s\n", outBuf); 20 | printf("Str len = %d\n", len); 21 | return(0); 22 | } 23 | -------------------------------------------------------------------------------- /Source Code/Chapter 9/uppertst4.c: -------------------------------------------------------------------------------- 1 | // 2 | // C program to embed our Assembly 3 | // toupper routine inline. 4 | // 5 | 6 | #include 7 | 8 | extern int mytoupper( char *, char * ); 9 | 10 | #define MAX_BUFFSIZE 255 11 | int main() 12 | { 13 | char *str = "This is a test."; 14 | char outBuf[MAX_BUFFSIZE]; 15 | int len; 16 | 17 | asm 18 | ( 19 | "MOV R4, %2\n" 20 | "loop: LDRB R5, [%1], #1\n" 21 | "CMP R5, #'z'\n" 22 | "BGT cont\n" 23 | "CMP R5, #'a'\n" 24 | "BLT cont\n" 25 | "SUB R5, #('a'-'A')\n" 26 | "cont: STRB R5, [%2], #1\n" 27 | "CMP R5, #0\n" 28 | "BNE loop\n" 29 | "SUB %0, %2, R4\n" 30 | : "=r" (len) 31 | : "r" (str), "r" (outBuf) 32 | : "r4", "r5" 33 | ); 34 | 35 | printf("Before str: %s\n", str); 36 | printf("After str: %s\n", outBuf); 37 | printf("Str len = %d\n", len); 38 | return(0); 39 | } 40 | -------------------------------------------------------------------------------- /Source Code/Chapter 9/uppertst5.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | 3 | libupper = CDLL("libup.so") 4 | 5 | libupper.mytoupper.argtypes = [c_char_p, c_char_p] 6 | libupper.mytoupper.restype = c_int 7 | 8 | inStr = create_string_buffer(b"This is a test!") 9 | outStr = create_string_buffer(250) 10 | 11 | len = libupper.mytoupper(inStr, outStr) 12 | 13 | print(inStr.value) 14 | print(outStr.value) 15 | print(len) --------------------------------------------------------------------------------