Exit in Assembly Language

Here’s the translation of the Go code to Assembly Language, formatted in Markdown suitable for Hugo:

section .data
    exit_msg db '!', 0

section .text
    global _start

_start:
    ; Exit with status 3
    mov eax, 1      ; syscall number for exit
    mov ebx, 3      ; exit status
    int 0x80        ; make syscall

    ; This part will never be executed
    mov eax, 4      ; syscall number for write
    mov ebx, 1      ; file descriptor (stdout)
    mov ecx, exit_msg
    mov edx, 1      ; message length
    int 0x80        ; make syscall

In Assembly Language, we don’t have direct equivalents to high-level concepts like defer. Instead, we structure our code to achieve similar results. Here’s an explanation of the code:

  1. We define a data section with our message “!”.

  2. In the _start function (the entry point for many assemblers):

    • We use the exit system call (syscall number 1 on many systems) to immediately exit with status 3.

    • The code to print “!” is placed after the exit call, demonstrating that it will never be executed.

To assemble and link this program (assuming x86 assembly on a Linux-like system):

$ nasm -f elf exit.asm
$ ld -m elf_i386 -o exit exit.o

Now you can run the program and check its exit status:

$ ./exit
$ echo $?
3

Note that the “!” message is never printed, as the program exits before reaching that code.

In Assembly, we directly use system calls to exit the program with a specific status. This is analogous to using os.Exit() in higher-level languages.

Unlike higher-level languages, Assembly gives you direct control over program flow and system interactions. This means you need to be more explicit about what the program does, including how it exits and what status it returns.