Writing non 64-bit x86 Assembly, Making Direct Syscalls

Non 64-bit x86 code

This whole semester, we've been writing x86 code in 64-bit mode, where registers and pointers are 64 bits long.

In previous years, I've taught this class in 32-bit mode, where
registers and pointers are 32 bits long. "rax" doesn't exist in
32-bit mode, but "eax" still does. Virtually everything works
exactly the same in 64-bit, 32-bit, or even the (much older) 16-bit
mode. In particular, almost all the data movement and arithmetic
instructions are ancient.

Other than that, 32-bit assembly is pretty nearly identical to 64-bit assembly!

Make a direct syscall

Normally, to interact with the outside world (files, network, etc) you
just call some function, usually the exact same function you'd call
from C or C++. But sometimes, such as when you're implementing
a C library, or when there is no C library call to access the
functionality you need, you want to talk to the OS kernel
directly. There's a special x86 "interrupt" instruction to do
this, called "int".

On Linux, you talk to the OS by loading up
values into registers then calling "int 0x80". Register rax
describes what to do (open a file, write data, etc) and rbx, rcx, rdx,
rsi, and rdi have the parameters describing how to do it. This
register-based parameter passing is similar to how we call functions in
64-bit x86, but the Linux kernel uses this convention both in 32 and 64
bit mode. Other operating systems like BSD store syscall
parameters on the stack, like the 32-bit x86 call interface!

; System calls are listed in "asm/unistd.h"mov rax,4 ; the system call number of "write".mov rbx,1 ; first parameter: 1, the stdout file descriptormov rcx,myStr ; data to writemov rdx,3 ; bytes to writeint 0x80 ; Issue the system call