Defer in Assembly Language

Assembly language doesn’t have a direct equivalent to Go’s defer keyword. However, we can demonstrate a similar concept using function calls and stack manipulation. This example will show how to simulate a deferred function call in assembly.

Our program will create a file, write to it, and then close it. We’ll use x86 assembly for this example.

section .data
    filename db "/tmp/defer.txt", 0
    create_msg db "creating", 10, 0
    write_msg db "writing", 10, 0
    close_msg db "closing", 10, 0
    data_msg db "data", 10, 0

section .text
    global _start

_start:
    ; Simulate creating a file
    call create_file
    
    ; Store the file descriptor on the stack (simulating defer)
    push eax
    
    ; Write to the file
    call write_file
    
    ; Close the file (simulated defer)
    call close_file
    
    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

create_file:
    ; Print "creating" message
    mov eax, 4
    mov ebx, 1
    mov ecx, create_msg
    mov edx, 9
    int 0x80
    
    ; Create the file
    mov eax, 8
    mov ebx, filename
    mov ecx, 0644o
    int 0x80
    
    ret

write_file:
    ; Print "writing" message
    mov eax, 4
    mov ebx, 1
    mov ecx, write_msg
    mov edx, 8
    int 0x80
    
    ; Write to the file
    mov ebx, [esp]  ; Get file descriptor from stack
    mov eax, 4
    mov ecx, data_msg
    mov edx, 5
    int 0x80
    
    ret

close_file:
    ; Print "closing" message
    mov eax, 4
    mov ebx, 1
    mov ecx, close_msg
    mov edx, 8
    int 0x80
    
    ; Close the file
    mov eax, 6
    pop ebx  ; Get file descriptor from stack
    int 0x80
    
    ret

In this assembly code:

  1. We define the necessary data in the .data section, including file name and messages.

  2. In the _start function:

    • We call create_file to create the file.
    • We push the file descriptor onto the stack, simulating a deferred close operation.
    • We call write_file to write to the file.
    • We call close_file, which will pop the file descriptor from the stack and close the file.
  3. The create_file function:

    • Prints “creating” message.
    • Creates a file using the creat system call (8).
  4. The write_file function:

    • Prints “writing” message.
    • Writes “data” to the file using the write system call (4).
  5. The close_file function:

    • Prints “closing” message.
    • Closes the file using the close system call (6).

To run this program:

  1. Save the code in a file, e.g., defer.asm.
  2. Assemble and link the program:
$ nasm -f elf defer.asm
$ ld -m elf_i386 -o defer defer.o
  1. Run the program:
$ ./defer
creating
writing
closing

This assembly code demonstrates a simple way to simulate deferred operations by using the stack to store and retrieve the file descriptor. While it’s not as elegant or automatic as Go’s defer keyword, it achieves a similar result of ensuring the file is closed after all operations are completed.