System calls, FFI, and cross-platform abstractions 55 Aside from different register naming, there is not that much difference from the one we wrote for Linux, with the exception of the fact that a write operation has the code 4 on mac OS instead of 1 as it did on Linux. Also, the CPU instruction that issues a software interrupt is svc 0 instead of syscall. Again, if you run this on mac OS, you'll get the following printed to your console: Hello world from raw syscall! What about raw syscalls on Windows? This is a good opportunity to explain why writing raw syscalls, as we just did, is a bad idea if you want your program or library to work across platforms. Y ou see, if you want your code to work far into the future, you have to worry about what guarantees the OS gives. Linux guarantees that, for example, the value 1 written to the rax register will always refer to write, but Linux works on many platforms, and not everyone uses the same CPU architecture. We have the same problem with mac OS that just recently changed from using an Intel-based x86_64 architecture to an ARM 64-based architecture. Windows gives absolutely zero guarantees when it comes to low-level internals such as this. Windows has changed its internals numerous times and provides no official documentation on this matter. The only things we have are reverse-engineered tables that you can find on the internet, but these are not a robust solution since what was a write syscall can be changed to a delete syscall the next time you run Windows update. Even if that's unlikely, you have no guarantee, which in turn makes it impossible for you to guarantee to users of your program that it's going to work in the future. So, while raw syscalls in theory do work and are good to be familiar with, they mostly serve as an example of why we' d rather link to the libraries that the different operating systems supply for us when making syscalls. The next segment will show how we do just that. The next level of abstraction The next level of abstraction is to use the API, which all three operating systems provide for us. We'll soon see that this abstraction helps us remove some code. In this specific example, the syscall is the same on Linux and on mac OS, so we only need to worry if we're on Windows. We can differentiate between the platforms by using the #[cfg(target_family = "windows")] and #[cfg(target_family = "unix")] conditional compilation flags. Y ou'll see these used in the example in the repository. Our main function will look the same as it did before: ch03/b-normal-syscall use std::io; fn main() {