Skip to content

Commit 0104c2b

Browse files
authored
Merge pull request #33 from below/2022q1_update
Update for macOS 12.3
2 parents d1d4850 + c7a3689 commit 0104c2b

File tree

2 files changed

+43
-21
lines changed

2 files changed

+43
-21
lines changed

Chapter 01/makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ HelloWorld: HelloWorld.o
22
ld -o HelloWorld HelloWorld.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
33

44
HelloWorld.o: HelloWorld.s
5-
as -o HelloWorld.o HelloWorld.s
5+
as -arch arm64 -o HelloWorld.o HelloWorld.s

README.md

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ An introduction to assembly on Apple Silicon Macs.
44

55
## Introduction
66

7-
In this repository, I will code along with the book [Programming with 64-Bit ARM Assembly Language](https://www.apress.com/de/book/9781484258804?utm_medium=affiliate&utm_source=commission_junction&utm_campaign=3_nsn6445_product_PID%zp&utm_content=de_05032018#otherversion=9781484258804), adjusting all sample code for Apple's ARM64 line of computers. While Apple's marketing material seems to avoid a name for the platform and talks only about the M1 processor, the developer documentation uses the term "Apple Silicon". I will use this term in the following.
7+
In this repository, I will code along with the book [Programming with 64-Bit ARM Assembly Language](https://www.dpbolvw.net/click-100586055-13091548?url=https%3A%2F%2Flink.springer.com%2Fbook%2F10.1007%2F978-1-4842-5881-1), adjusting all sample code for Apple's ARM64 line of computers. While Apple's marketing material seems to avoid a name for the platform and talks only about the M1 processor, the developer documentation uses the term "Apple Silicon". I will use this term in the following.
88

99
The original sourcecode can be found [here](https://github.com/Apress/programming-with-64-bit-ARM-assembly-language).
1010

@@ -21,7 +21,7 @@ While I pretty much assume that people who made it here meet most if not all req
2121

2222
## Acknowledgments
2323

24-
I would like to thank @claui, @jannau, @jrosengarden, @m-schmidt, @saagarjha, and @zhuowei! They helped me when I hit a wall, or asked questions that let me improve the content.
24+
I would like to thank [@claui](https://github.com/claui), [@jannau](https://github.com/jannau), [@jrosengarden](https://github.com/jrosengarden), [@m-schmidt](https://github.com/m-schmidt), [@saagarjha](https://github.com/saagarjha), and [@zhuowei](https://github.com/zhuoweir)! They helped me when I hit a wall, or asked questions that let me improve the content.
2525

2626
## Changes To The Book
2727

@@ -31,7 +31,7 @@ Linux and Darwin, which were both inspired by [AT&T Unix System V](http://www.un
3131

3232
This file is organized so that you can read the book, and read about the differences for Apple Silicon side by side. The headlines in this document follow those in the book.
3333

34-
## Chapter 1
34+
## Chapter 1: Getting Started
3535

3636
### Computers and Numbers
3737

@@ -89,7 +89,7 @@ We know the `-o` switch, let's examine the others:
8989
* `-e _start`: Darwin expects an entrypoint `_main`. In order to keep the sample both as close as possible to the book, and to allow it's use within the C-Sample from _Chapter 3_, I opted to keep `_start` and tell the linker that this is the entry point we want to use
9090
* `-arch arm64` for good measure, let's throw in the option to cross-compile this from an Intel Mac. You can leave this off when running on Apple Silicon.
9191

92-
## Chapter 2
92+
## Chapter 2: Loading and Adding
9393

9494
The changes from [Chapter 1](https://github.com/below/HelloSilicon#chapter-1) (makefile, alignment, system calls) have to be applied.
9595

@@ -105,7 +105,7 @@ ADD X2, X1, W0, SXTB
105105
```
106106
The GNU Assembler seems to ignore this and allows you to specifiy a 64-Bit source register.
107107

108-
## Chapter 3
108+
## Chapter 3: Tooling Up
109109

110110
### Beginning GDB
111111

@@ -162,7 +162,7 @@ That said, while it is possible to build an iOS executable with the command line
162162

163163
As [Chapter 10](https://github.com/below/HelloSilicon#chapter-10) focusses on building an app that will run on iOS, I have chosen to simply create a Command Line Tool here which is now using the same `HelloWorld.s` file.
164164

165-
## Chapter 4
165+
## Chapter 4: Controlling Programm Flow
166166

167167
Besides the common changes, we face a new issue which is described in the book in Chapter 5: Darwin does not like `LSR X1, =symbol`, it will produce the error `ld: Absolute addressing not allowed in arm64 code`. If we use `ASR X1, symbol`, as suggested in Chapter 3 of the book, our data has to be in the read-only `.text` section. In this sample however, we want writable data.
168168

@@ -193,7 +193,7 @@ I was asked how to read the command line, and I gladly [answered](https://github
193193

194194
Sample code can be found in Chapter 4 in the file [`case.s`](Chapter%2004/case.s).
195195

196-
## Chapter 5
196+
## Chapter 5: Thanks for the Memories
197197

198198
The important differences in memory addressing for Darwin were already addresed above.
199199

@@ -204,22 +204,22 @@ The `quad`, `octa` and `fill` keywords must be in lowercase for the llvm assembl
204204

205205
Changes like in Chapter 4.
206206

207-
## Chapter 6
207+
## Chapter 6: Functions and the Stack
208208

209209
As we learned in Chapter 5, all assembler directives (like `.equ`) must be in lowercase.
210210

211-
## Chapter 7
211+
## Chapter 7: Linux Operating System Services
212212
`asm/unistd.h` does not exist in the Apple SDKs, instead `sys/syscalls.h` can be used.
213213

214214
It is also important to notice that while the calls and definitions look similar, Linux and Darwin are not the same: `AT_FDCWD` is -100 on Linux, but must be -2 on Darwin.
215215

216216
Unlike Linux, errors are signified by setting the carry flag, and the error codes are non-negative. We therefore `MOV` the result into the required register instead of `ADDS` (we don't need to check for negative numbers, and need to preserve the condition flags) and B.CC to the success path.
217217

218-
## Chapter 8
218+
## Chapter 8: Programming GPIO Pins
219219

220220
This chapter is specifically for the Raspberry Pi 4, so there is nothing to do here.
221221

222-
## Chapter 9
222+
## Chapter 9: Interacting with C and Python
223223

224224
For transparency reasons, I replaced `gcc` with `clang`.
225225

@@ -266,27 +266,49 @@ While we are using the LLVM toolchain, in assembly — including inline-assembly
266266

267267
Also, the size of one variable had to be changed from int to long to make the compiler complete happy and remove all warnings
268268

269+
### Calling Assembly from Python
270+
271+
Note that as of this writing, all Python IDEs for macOS attempt to load x86\_64 libraries, even when the app itself is universal. So currently the only way to run the sample is on the command line. Also, as of macOS 12.3, Apple [removed Python 2](https://developer.apple.com/documentation/macos-release-notes/macos-12_3-release-notes), and developers should use Python 3.
272+
269273
### Listing 9-9
270274

271-
While the `uppertst5.py` file only needed a minimal change, calling the code is a little more challenging: On Apple Silicon Macs, python is a Mach-O universal binary with two architectures: x86_64 and arm64e. Notably absent is the arm64 architecture we were building for up to this point. This makes our dylib unusable with python.
275+
While the `uppertst5.py` file only needed a minimal change, calling the code is a little more challenging. On Apple Silicon Macs, Python is a Mach-O universal binary with two architectures, x86\_64 and arm64e:
276+
277+
```
278+
% lipo -info /usr/bin/python3
279+
Architectures in the fat file: /usr/bin/python3 are: x86_64 arm64e
280+
```
281+
282+
Notably absent is the arm64 architecture we were building for up to this point. This makes our dylib unusable with Python.
272283

273284
arm64e is the [Armv-8 architecture](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-a-architecture-2016-additions), which Apple is using since the A12 chip. If you want to address devices prior to the A12, you must stick to arm64. The first Macs to use ARM64 run on the M1 CPU based on the A14 architecture, thus Apple decided to take advangage of the new features.
274285

275286
So, what to do? We could compile everything as arm64e, but that would make the library useless on devices like the iPhone X or older, and we would like to support them, too.
276287

277-
Above, you read something about a _universal binary_. For a very long time, the Mach-O executable format had support for several processor architectures in a single file. This includes, but is not limited to, Motorola 68k (on NeXT computers), PowerPC, Intel x86, as well ARM code, each with their 32 and 64 bit variantes where applicable. In this case, I am building a universal dynamic library which includes both arm64 and arm64e code. More information can be found [here](https://developer.apple.com/documentation/xcode/building_a_universal_macos_binary).
288+
Above, you read something about a _universal binary_. For a very long time, the Mach-O executable format was supporting several processor architectures in a single file. This includes, but is not limited to, Motorola 68k (on NeXT computers), PowerPC, Intel x86, as well ARM code, each with their 32 and 64 bit variantes where applicable. In this case, I am building a universal dynamic library which includes both arm64 and arm64e code. More information can be found [here](https://developer.apple.com/documentation/xcode/building_a_universal_macos_binary).
289+
290+
As mentioned above, no currently available Python IDE on macOS will load the ARM64 library, so use the command line to run your code:
291+
292+
```
293+
% python3 uppertst5.py
294+
b'This is a test!'
295+
b'THIS IS A TEST!'
296+
16
297+
```
298+
299+
## Chapter 10: Interfacing with Kotlin and Swift
278300

279-
## Chapter 10
280301
No changes in the core code were required, but instead of just an iOS app I created a SwiftUI app that will work on macOS, iOS, watchOS (Series 4 and later), and tvOS.
281302

282-
## Chapter 11
303+
## Chapter 11: Multiply, Divide, and Accumulate
304+
283305
At this point, the changes should be self-explainatory. The usual makefile adjustments, `.align 4`, address mode changes, and `_printf` adjustments.
284306

285-
## Chapter 12
307+
## Chapter 12: Floating-Point Operations
286308

287309
Like in Chapter 11, all the chages have been introduced already. Nothing new here.
288310

289-
## Chapter 13
311+
## Chapter 13: Neon Coprocessor
290312

291313
Once again, the Clang assembler wants a slightly different syntax: Where gcc accepts
292314

@@ -302,11 +324,11 @@ MUL.4H V6, V0, V3[0]
302324

303325
All other changes to the code should be trivial at this point.
304326

305-
## Chapter 14
327+
## Chapter 14: Optimizing Code
306328

307329
No unusal changes here.
308330

309-
## Chapter 15
331+
## Chapter 15: Reading and Understanding Code
310332

311333
### Copying a Page of Memory
312334

@@ -321,7 +343,7 @@ No changes were required. The "tiny" code model is not supported for Mach-O exce
321343
fatal error: error in backend: tiny code model is only supported on ELF
322344
```
323345

324-
## Chapter 16
346+
## Chapter 16: Hacking Code
325347

326348
All that can be said is that clang automatically enables position-independent executables, and the option `-no-pie` does not work. Therefore, the exploit shown in the `upper.s` file can not be reproduced.
327349

0 commit comments

Comments
 (0)