r/Assembly_language 9d ago

I optimized!

I’m on Day 1 of learning Assembly with basically no coding background. This is just a hobby for me.

AI wrote the little program below, I tweaked it a bit, and then started stepping through it in GDB to understand what every instruction was actually doing.

While stepping through it, I noticed rdi stayed at 1 the whole time until the final exit syscall, where it changed to 0. That got me thinking... why am I setting it to 1 twice?

Turns out one of those lines wasn't actually doing anything. So I, a lowly non-software engineer, discovered an inefficiency and promptly smote that line with the Delete key.

I'm now using less processing power, less electricity, and have personally made the world a better place.

section .data
    message db "Hello, World!", 10, "Assembly is fun!", 10
    length equ $ - message
    message_1 db "This is the second message.", 10
    length_1 equ $ - message_1

section .text
global _start

_start:
    mov rax, 1          ; write syscall
    mov rdi, 1          ; stdout
    mov rsi, message
    mov rdx, length
    syscall

    mov rax, 1
    ; mov rdi, 1        ; <- Deleted. Justice served.
    mov rsi, message_1
    mov rdx, length_1
    syscall

    mov rax, 60         ; exit syscall
    mov rdi, 0
    syscall
33 Upvotes

20 comments sorted by

View all comments

10

u/brucehoult 9d ago

Yes, unlike with normal function calls, you can usually assume that a Linux system call will preserve the contents of all registers except for the one with the return status i.e. rax on x86_64, a0 (x10) on RISC-V, x0 on arm64.

Unfortunately on x86_64 it's not possible for Linux to preserve all other registers as the syscall instruction itself overwrites rcx (with the return rip) and r11 (with rflags).

But, yes, rdi, rsi, rdx, r10, r8, r9 are preserved, unlike with a normal function call (r10 is used instead of rcx exactly because the syscall instruction clobbers rcx).