本文由 简悦SimpRead 转码, 原文地址 smist08.wordpress.com
引言 上周,我们讨论了使用基于苹果 M1 的新 Macintosh 作为开发工作站的问题......。
上周,我们讨论了如何使用基于苹果 M1 的新 Macintosh 作为开发工作站,以及安装苹果开发系统 XCode 的同时如何安装大量开源开发工具,包括 LLVM 和 make。本周,我们将介绍如何编译和运行一个简单的命令行 ARM 汇编语言 Hello World 程序。
我的书"使用 64 位 ARM 汇编语言编程 "包含大量自包含的汇编语言程序示例以及大量 iOS 和 Android 示例。命令行实用程序是使用 GNU 工具集为 Linux 编译的。Alex vonBelow 采用了所有这些工具,并对其进行了修改,使其能与 LLVM 工具链配合使用,并能在苹果公司的开发环境中运行。他还处理了 Linux 和 MacOS/iOS 之间的所有差异。他为我的书修改的源代码版本(适用于 Apple M1)可在此处获取:
MacOS 和 Linux 都基于 Unix,相似之处多于不同之处。但也有一些值得注意的不同之处:
- MacOS 默认使用 LLVM,而 Linux 使用 GNU GCC。就本文而言,这实际上只是影响了 makefile 中的命令行参数。你可以在 Linux 上使用 LLVM,GCC 不久也会在苹果 M1 上推出。
- MacOS 的链接器/加载器不喜欢进行重定位,因此你需要使用 ADR 而不是 LDR 指令来加载地址。你可以在 Linux 中使用 ADR,这样在两种系统中都能使用。
- Unix API 调用几乎是一样的,区别在于 Linux 在升级到 64 位时重新编排了函数编号,而 MacOS 则保持不变。在 32 位世界中,它们是一样的,但现在它们都不一样了。
- 在调用 Linux 服务时,函数编号将使用 X16 而不是 X8。
- Linux将各种库和包含文件安装在/usr/lib和/usr/include下,因此它们很容易找到和使用。当你安装 XCode 时,它会为 MacOS、iOS、iPadOS、iWatchOS 等安装 SDK,并可选择安装多个版本。库和包含库的路径相当复杂,你需要一个工具来找到它们。
- 在 MacOS 中,程序必须以 64 位边界启动,因此列表顶部有一个".align 2 "指令。
- 在 MacOS 中,即使不进行系统调用,也需要链接 System 库,否则链接器会出错。这个 Hello World 示例程序使用软件中断进行系统调用,而不是使用系统库中的 API,因此不需要链接到系统库。
- 在 MacOS 中,默认入口点是
_main,而在 Linux 中则是_start。这可以通过链接器的命令行参数来更改。
Hello World Assembly File
下面是在终端窗口中打印 "Hello World "的简单汇编语言程序。有关这些指令和 ARM 处理器架构的所有细节,请查阅我的 书。
//
// Assembler program to print "Hello World!"
// to stdout.
//
// X0-X2 - parameters to linux function services
// X16 - linux function number
//
.global _start // Provide program starting address to linker
.align 2
// Setup the parameters to print hello world
// and then call Linux to do it.
_start: mov X0, #1 // 1 = StdOut
adr X1, helloworld // string to print
mov X2, #13 // length of our string
mov X16, #4 // MacOS write system call
svc 0 // Call linux to output the string
// Setup the parameters to exit the program
// and then call Linux to do it.
mov X0, #0 // Use 0 return code
mov X16, #1 // Service command code 1 terminates this program
svc 0 // Call MacOS to terminate the program
helloworld: .ascii "Hello World!\n"
Makefile
下面是 makefile,组装源代码的命令很简单,链接的命令就比较复杂了。
HelloWorld: HelloWorld.o
ld -macosx_version_min 11.0.0 -o HelloWorld HelloWorld.o -lSystem -syslibroot
`xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
HelloWorld.o: HelloWorld.s
as -o HelloWorld.o HelloWorld.s
xcrun 命令是苹果公司运行或查找各种 SDK 的命令。下面是运行它的示例:
stephensmith@Stephens-MacBook-Air-2 ~ % xcrun -sdk macosx –show-sdk-path
objc[42012]: Class AMSupportURLConnectionDelegate is implemented in both ?? (0x1edb5b8f0) and ?? (0x122dd02b8). One of the two will be used. Which one is undefined.
objc[42012]: Class AMSupportURLSession is implemented in both ?? (0x1edb5b940) and ?? (0x122dd0308). One of the two will be used. Which one is undefined.
objc[42013]: Class AMSupportURLConnectionDelegate is implemented in both ?? (0x1edb5b8f0) and ?? (0x1141942b8). One of the two will be used. Which one is undefined.
objc[42013]: Class AMSupportURLSession is implemented in both ?? (0x1edb5b940) and ?? (0x114194308). One of the two will be used. Which one is undefined.
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk
stephensmith@Stephens-MacBook-Air-2 ~ %
在 Objective-C 发出难看的警告后,MacOS SDK 的路径就会显示出来。
现在我们可以编译并运行我们的程序了。
stephensmith@Stephens-MacBook-Air-2 Chapter 1 % make -B
as -o HelloWorld.o HelloWorld.s
objc[42104]: Class AMSupportURLConnectionDelegate is implemented in both ?? (0x1edb5b8f0) and ?? (0x1145342b8). One of the two will be used. Which one is undefined.
objc[42104]: Class AMSupportURLSession is implemented in both ?? (0x1edb5b940) and ?? (0x114534308). One of the two will be used. Which one is undefined.
ld -macosx_version_min 11.0.0 -o HelloWorld HelloWorld.o -lSystem -syslibroot `xcrun -sdk macosx –show-sdk-path` -e _start -arch arm64
stephensmith@Stephens-MacBook-Air-2 Chapter 1 % ./HelloWorld
Hello World!
stephensmith@Stephens-MacBook-Air-2 Chapter 1 %
作为 Apple Silicon 的一部分,新的 Apple M1 Macintos 正在运行 ARM 处理器,您可以运行标准的 ARM 64 位汇编语言。LLVM 是一个标准的开源开发工具,它包含一个类似于 GNU 汇编程序的汇编程序。MacOS 的编程与 Linux 相似,因为两者都基于 Unix,如果你熟悉 Linux,那么大部分知识都可以直接应用。