The iMac Pro/M1

Written by randyhyde@me.com on March 14, 2021 in General with 8 comments.

Recently I decided it was about time to translate my “Art of Assembly Language” book from the 80×86 CPU to the ARM processor. Of course, the first question I had to answer was “which ARM CPU to use?” There are a wide variety of ARM CPUs out there, with different instruction sets. There are 32-bit ARM microcontrollers that are very popular in embedded systems (such as the M0 Cortex and M4 Cortex CPUs, typically found in single-board computers such as the Teensy 4.x or the Raspberry Pico). There are tons of ARM-based 32-bit microcontroller boards out there; STM makes a huge number, Adafruit, Sparkfun, and Seeed Studio produce a bunch of them. Of course, the Raspberry Pi (prior to the Pi 3 & 4) used 32-bit CPUs (A11, amongst others). Today the Pi Zero and Zero W still use 32-bit CPUs. For this reason, the Raspberry Pi OS (a Linux variant) runs in 32-bit mode, even on the 64-bit Pi 3 & 4 machines. Tons of 32-bit ARM machines are still being sold today.

However, 32-bits is so…. 1990s. Ever since Apple introduced 64-bit CPUs in their iPhone and iPad lines (and Android followed within a few years), 64 bits has been “where it’s at.” Then, of course, Apple announced the Apple Silicon M1 series of CPUs whose “system on a chip” performance was blowing away contemporary x86 PCs. With all the buzz, it became clear to me that I had to leave 32-bits behind and concentrate on 64-bit ARM assembly language.

Mind you, I’m not interested in writing “The Art of ARM Assembly” strictly for the Apple Mx-series computer systems. There are a large number of 64-bit ARM machines laying around, all of which can be programmed using the 64-bit variant of the GNU “as” assembler (hereafter, “gas”). My current plans are to ensure that all the example programs will compile (assemble) and run on the following systems:

  • Mac systems based on the Mx series CPUs (e.g., the M1)
  • Raspberry Pi 3 & 4 system running a 64-bit version of Pi OS or Linux
  • Jetson Nano boards running a 64-bit version of Linux
  • Pine 64/RockPro/PineTop 64-based systems running a 64-bit version of Linux

As I write this, I’m currently receiving the final edits and layouts of my new book “The Art of 64-Bit Assembly Language” from No Starch Press (https://www.nostarch.com). This book is a rewrite of my earlier “The Art of Assembly Language” using 64-bit x86-64 assembly language on a Windows PC (with the Microsoft MASM assembler). As the chapters come in for the x86 book, I’m going to rewrite them using ARM assembly language. Now I already own a couple Pi 3 & 4 systems, the Pine 64 systems (Pine 64, RockPro 64, a Pine Top, and a Pine Top Pro), and a Jetson Nano board. I also own an iPhone and an iPad so I can test ARM assembly language running on those devices. The only thing missing was an Apple Mx-based system.

My original plan was to wait for the next system to arrive. My 16″ MacBook Pro has 64 GB RAM; my iMac Pro also has 64 GB RAM. The M1 Mini, with a maximum of 16GB is a bit anemic for my tastes. I feel that 32GB is the smallest “maximum RAM complement” a system should have. However, I really can’t afford to wait for the M2 (or whatever it will be) to arrive, so I broke down and bought a 16GB/2TB M1 Mac Mini so I could get started on the book.

The only problem with the M1 Mini is that I just don’t have the desk space for yet another Apple computer. I have an iMac Pro sitting on my desk already. Other tables around by workspace are filled with electronics gear and instrumentation (I develop PCBs and circuit boards for the nuclear industry). Furthermore, all my authoring tools run under Windows/Parallels (Adobe Framemaker and Canvas X being the primary ones). Generally, I’m running one or two Parallels windows on my iMac Pro (hence the need for 64GB RAM) while working on a book–one for Framemaker and one for compiling and running programs (assuming I’m not compiling and running them under macOS). Trying to juggle a separate computer on my desk for code development isn’t practical.

The solution was quite simple: the iMac Pro/M1. I’m already used to juggling multiple “computers” on my desktop (I have 14 different Parallels setups on my iMac Pro, allowing me to run various versions of Windows, macOS, Linux, and FreeBSD); why not just add another window for an ARM-based macOS? Of course, Parallels cannot emulate an ARM (M1) running macOS (nor would I want to use it, if it did), but it is possible to add a window on the iMac Pro providing access to my M1 Mini using Apple’s Remote Desktop application (about $80 on the App store). The reviews were terrible (1.8 out of 5 stars), so I was a bit concerned about spending this kind of money on the application only to find that it doesn’t do the job. However, I bought it and installed it, and it works sufficiently well for my purposes that I’m not going to complain too loudly about it. Yes, the screen refresh is a teensy bit slow; I wouldn’t want to edit video or play games on the M1 while operating from the iMac Pro, but for code development purposes it works just fine.

Some might question the sanity of using the M1 as a peripheral computer for the iMac Pro. After all, don’t all the benchmarks show the M1 blowing away Intel machines (like the several-year old Xeon CPU in the iMac Pro)? Well, the iMac Pro still has many advantages over the M1 Mini:

  • The iMac Pro has an incredibly beautiful screen. You have to spend a lot of money to get a screen this good.
  • The iMac Pro, with an x86-64 CPU, runs x86-based operating systems (like Windows, Linux, and Free BSD). Sure, most of those OSes have ARM variants, but often the applications are only available on the x86 (especially Windows).
  • The iMac Pro has 64GB memory (need I say more?). Granted, I use most of that memory running Parallels VMs (which aren’t available on the M1 Mini, so it doesn’t need quite as much memory), but there are some things I do where 16GB just isn’t quite enough.
  • The iMac Pro is running a lot of commercial software that I don’t feel like paying to upgrade to run on the M1. For example, cheap guy that I am, I’m still running Adobe CS6 (in a Parallels VM running Yosemite) because I’m morally opposed to subscription software. For the little that I use Photoshop and GoLive these days, it’s not worth the money to upgrade (especially to a subscription-based system). Also, I have lots of orphaned software that will never run on an M1 (as it’s 32-bit and won’t even run on the latest macOS).

Of course, the M1 Mini has lots of advantages as well. For example, it supposedly faster than the iMac Pro (don’t know, haven’t actually run any applications where the speed difference was important). The main advantage, to me, is that it has an ARM-based CPU which executes 64-bit ARM assembly code, so I can develop and test ARM assembly code for my book.

So my ultimate goal was to create an iMac Pro machine capable of compiling, running, and testing ARM assembly language code. Here’s how I did it:

  1. I set up the M1 Mini, updated the OS, and did all the normal stuff you do with a new machine. I did not bother copying any of my applications to the M1, as I’m perfectly happy running most of my code on the iMac Pro.
  2. I installed Xcode on the M1 Mini (to gain access to the GNU gas assembler and other tools).
  3. I installed Apple’s Remote Desktop application on my iMac Pro.
  4. I connected the M1 Mini to my local Ethernet (thereby connecting it to the iMac Pro).
  5. I booted the M1 Mini and started the Remote Desktop app. Logged on to the M1 Mini from the Remote Desktop Window.
  6. On the M1 Mini, I used to Go>Connect to Server Finder menu option to connect to my shared drive on the iMac Pro (where I keep all my data, including my book files and source code).
  7. Voila! I’m in business developing source code for The Art of ARM Assembly Language.

The cool thing about this approach is that I can now use different writing and development tools across multiple machines and operating systems. For example, I generally prefer editing program text using the CodeWright text editor under Windows (a really ancient program, from the 1990s) or BBEdit under macOS (versus Xcode, which is a bit bloated and not the most appropriate tool for writing ARM assembly language). Because I’ve got Windows running in one (or two) windows, macOS/x86 running on the iMac Pro, and macOS/ARM (M1) running in another window, all sharing the same information on my “data” network drive, it’s trivial to switch between systems, applications, and CPUs. All using my original, comfortable, workflow.

Although I cannot recommend anyone getting an iMac Pro to create their own iMac Pro/M1, this combination does demonstrate how to upgrade a (now discontinued) system. Of course, there is nothing iMac Pro-specific about my setup. You could pull this same trick with any iMac, or any Mac for that matter. Someday, of course, we’ll see Apple Silicon Mx-series CPUs in the iMac form factor. Until then, this is a convenient way to get the power of an M1 running on an existing x86 iMac system.

Some additional comments:

What about Windows on ARM?

I mentioned a set of ARM-based machines I intend to support when writing The Art of ARM Assembly. Noticeably absent from this list was Microsoft’s ARM-based Windows machines, such as the Surface X. I personally have nothing against Microsoft (I actually own two x86-based Surface machines). The problem with trying to support Microsoft ARM machines is that Microsoft uses their own assembler with a sufficiently different syntax from GAS that it would make it very confusing to include such code in the book containing GAS code. If I get my hands on a Surface X (or other MS ARM machine), I might add an appendix that describes the differences and put the MS-compatible source code on line. However, given the cost and low acceptance of MS-based ARM machines in the marketplace, this won’t be a very high priority.

What about 32-bit code?

Why not teach both 32-bit and 64-bit ARM assembly in the same book? The problem with that theory is that the 32-bit instruction set is substantially different from the 64-bit instruction set (it’s not like the x86 where you rename a few registers and you’re good to go). Attempting to pack both instruction sets into the same book would simply lead to confusion on the part of beginning assembly language programmers. So 32-bits, because it’s the “old fashioned” stuff, got nixed.

8 Responses to “The iMac Pro/M1

  1. Another very nice place to run gas on 64 bit arm is qemu. (In my view, an absolute must, for any arm64 book, or else I would refuse to consider it. Yes, allow me to make a strong statement every once in a while haha.)

    qemu runs on many platforms (on windows you can get it via msys2 with: pacman -S –needed mingw-w64-x86_64-qemu # that runs on the MSYS Mingw64 shell ).

  2. Mr Hyde,

    Any thoughts / rough estimates of when you think AoA for ARM will be done? If and when it does come out it will be at the top of my reading list.
    Thanks

    • I’m hoping for publication early next year. While translation the book from X86-64 to ARM is a much faster process than writing it from scratch, Ao64A is just shy of 1,000 pages, so there’s a lot of work to do. I’ve just finished translating chapter 3 (of 16) yesterday. I need to take some time off from that project (Ao64A is in the final editing/proofing stages right now and The Book of I2C is also demanding some of my time), but I hope to make a lot of progress on the book this summer.

  3. Yes so arm-linux-gnueabihf-as is all fine and dandy with ARM64 running on linux or a MAC.

    But what I would also want is this: a chapter on bare metal programming via arm-none-eabi-as
    (including cross-compilation with arm-none-eabi-as and running on qemu). Google: qemu arm c++ arm-none-eabi

    That’s just my perspective on things.

  4. Well, AoAA will be a relatively straight-forward translation of Art of 64-bit Assembly (itself a translation of The Art of Assembly). It’s intended audience is students learning machine organization and assembly language programming at the University level (in a second- or third-term course in Computer Science). So going crazy with less-than-commonly-used platforms is out of the question. Yes, a few people who prize portability above everything else might feel strongly about using mingw or qemu. However, basing a book around that would satisfy the few and turn off the many. Keep in mind, books like AoAA have to have an audience or publishers won’t touch them. AoAA was specifically done at this point because of the release of the Apple M1 — that dramatically increased the market for a book on 64-bit ARM assembly. However, I guarantee you that very few of that macOS M1 users would be interested in something like MINGW/qemu.

    That said, I *do* see the possibility of a Volume 2 way down the road subtitled: “32-bit ARM Assembly Language for Embedded Systems” to cover Raspberry PIs (32-bit OS), Arduino (with ARMs), Mbed/STM32, and other such devices. However, we’ll have to see how well AoAA does to see if it’s worth it.
    Cheers,
    Randy Hyde

    • Well ok.

      Another must-have from my perspective of an assembly book, is how to code in C/C++ and use custom runtime code generation, e.g. during the conversion of mathematical formulas which are then run millions of times.

      I’ve read “Programming from the ground up” many many years ago; and will never touch another assembly book (because of using C/C++ instead) unless it handles that topic.

      • That’s all well and good, but keep in mind that when an author writes a book on assembly language programming they’re probably targeting it at beginners who want to learn the basics of assembly language programming. What you’re looking for is something completely different.

        FWIW, “Write Great Code, Volume 2” looks very heavily at analyzing compiler output (to write efficient code in C/C++ without dropping down into assembly). That sounds like it’s more up your alley.

        I’m not sure what you mean by “custom runtime code generation.” But if that’s what I think you mean (generating code on the fly, such as game coding used to do back in the 1980s and 1990s, to handling sprites and the like), such code will either:
        1. not run on modern OSes that deal with position-independent executables/address space layout randomization and disallow such coding, or,
        2. will be a huge security risk; if you can rewrite code on the fly, so can a hacker/exploit.

        FWIW, NSP does have a Volume II of “The Art of 64-bit Assembly” in their possession (will likely start the editing phase later this year or early next year). Don’t know if it covers subjects you’re interested in, but it certain covers advanced subjects related to HLLs (sometimes more HL than C/C++):
        1 ADVANCED MACROS ………………………………………………….. 1-1
        2 UNICODE STRINGS …………………………………………………….. 2-1
        3 TRANSCENDENTAL FUNCTIONS …… …………………………….. 3-1
        4 ADVANCED PROCEDURES …………………………………………… 4-1
        5 CONCURRENT PROGRAMMING ……………………………………. 5-1
        6 OBJECT-ORIENTED PROGRAMMING WITH MASM …………. 6-1
        7 EXCEPTION HANDLING ………………………………………………. 7-1
        8 THUNKS AND CLOSURES …………………………………………….. 8-1
        9 ADVANCED PARAMETER IMPLEMENTATION ……………….. 9-1
        10 ITERATORS ……………………………………………………………. 10-1
        11 COROUTINES, GENERATORS, AND FIBERS ………………… 11-1

Leave a Reply to Al Cancel reply

Your email address will not be published.