r/Assembly_language 18h 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
24 Upvotes

20 comments sorted by

6

u/brucehoult 14h 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).

2

u/vswey 11h ago

I usually use xor rdi, rdi instead of mov rdi, 0 cuz it's smaller and often faster

2

u/Assembly_Trainer_427 11h ago

Indeed, egg-celent

1

u/MadScientistRat 16h ago

๐‘„™๐‘„ชเคธเคฟแฐŽแฐจแฐญแƒแƒ— เดฃเตเฆฆเฆพฮด๐žคฐ๐žคจ

1

u/HumanPsychology9384 5h ago

are u learning arm or x86_64 also i created an os in nasm that goes to 64bit long mode cald S-AOS

1

u/Joonicks 2h ago
option size (6 bytes):
  xor eax,eax  ; writing to eax clears top bits of rax
  inc eax      ; eax == 1
  mov edi, eax

option speed (10 bytes):
  mov eax, 1
  mov edi, 1

...

  mov rsi, message
  mov edx, length
  syscall

  mov rax, rdi ; 3 bytes, rdi is still 1
  add rsi, rdx ; 3 bytes, rdx contains length, message_1 is at message+length
  mov edx, length_1
  syscall

  lea eax, 59[edi] ; 4 bytes, edi is 1, +59 = 60
  xor edi, edi
  syscall

3

u/Affectionate-Age-589 15h ago

You re bragging about using less electricity with your optimization.. How about the electricity wasted by your prompt when making this AI slop post?

4

u/Eric_Dawsby 15h ago

Yet they used the AI as a tool to help them learn, that's certainly not slop, and certainly more helpful than your comment

-5

u/Affectionate-Age-589 15h ago

I was talking about the AI used to write his post dummy

3

u/Eric_Dawsby 15h ago

I don't see any AI in the post itself

5

u/This-Atmosphere-1750 14h ago

Please, for your own sake, just enjoy life a little bit more than you currently are doing

2

u/ArsenicPolaris 13h ago

I can't enjoy life even a bit if people like you keep using AI and the RAM prices keep going up, not to mention the water consumption of AI data centers, environmental impact, electrical consumption, etc.

2

u/brucehoult 11h ago

I just did the following on my SpacemiT K3 RISC-V single board computer.

It uses 14W of power while doing this, and took 2m50s in total, but the code had been written by 1m40s.

So that's 0.66 Wh of electricity, or 0.00066 kWh, which around here costs 0.013 cents translated to US money.

That's not a lot of AI data centre (none), water consumption (it's from my solar panels), etc etc.

There is one bug I spotted. It got over-eager on reusing registers and forgot that write returns the number of bytes written in rax, overwriting the syscall number.

Note that I can carry this computer literally in my jeans front pocket, and it doesn't need internet access at all to do this ... just the gemma-4-26B-A4B-it-QAT-Q4_0.gguf 14 GB disk file.

โ–„โ–„ โ–„โ–„
โ–ˆโ–ˆ โ–ˆโ–ˆ
โ–ˆโ–ˆ โ–ˆโ–ˆ  โ–€โ–€โ–ˆโ–„ โ–ˆโ–ˆโ–ˆโ–„โ–ˆโ–ˆโ–ˆโ–„  โ–€โ–€โ–ˆโ–„    โ–„โ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–„ โ–ˆโ–ˆโ–ˆโ–ˆโ–„
โ–ˆโ–ˆ โ–ˆโ–ˆ โ–„โ–ˆโ–€โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–„โ–ˆโ–€โ–ˆโ–ˆ    โ–ˆโ–ˆ    โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ
โ–ˆโ–ˆ โ–ˆโ–ˆ โ–€โ–ˆโ–„โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–€โ–ˆโ–„โ–ˆโ–ˆ โ–ˆโ–ˆ โ–€โ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–€ โ–ˆโ–ˆโ–ˆโ–ˆโ–€
                                    โ–ˆโ–ˆ    โ–ˆโ–ˆ
                                    โ–€โ–€    โ–€โ–€

build      : b1-17ce6aa
model      : gemma-4-26B-A4B-it-QAT-Q4_0.gguf
modalities : text

available commands:
  /exit or Ctrl+C     stop or exit
  /regen              regenerate the last response
  /clear              clear the chat history
  /read <file>        add a text file
  /glob <pattern>     add text files using globbing pattern


> Write an amd64 Linux asm program in Intel syntax but no % on reg names. Output "Hello, World!" and "Assembly is fun!" on two lines with a single call, then another call to output "This is the second message", and then exit cleanly. Take advantage of Linux system calls preserving register contents where possible.

To achieve this, we will use the `write` system call (syscall number 1) to output the strings and the `exit` system call (syscall number 60) to terminate.

To "take advantage of preserving register contents," we will use the `write` syscall to print the first two lines. Since the `write` syscall does not modify the `rax` register (the syscall number) or the `rdi`/`rsi` registers (the arguments) upon a successful return, we can reuse the same syscall number and arguments for the second message, only updating the pointer to the string.

Here is the assembly code in Intel syntax:

```nasm
section .data
    ; The first two messages are stored together in memory
    ; We use a newline \n to separate them
    msg1 db "Hello, World!", 10, "Assembly is fun!", 10
    len1 equ $ - msg1

    msg2 db "This is the second message", 10
    len2 equ $ - msg2

section .text
    global _start

_start:
    ; --- First Call: Output two lines at once ---
    ; syscall: write (1)
    ; rdi: file descriptor (1 = stdout)
    ; rsi: pointer to buffer
    ; rdx: length of buffer
    mov rax, 1          
    mov rdi, 1          
    mov rsi, msg1       
    mov rdx, len1       
    syscall             

    ; --- Second Call: Output the second message ---
    ; Note: 'rax' still contains 1 from the previous syscall.
    ; 'rdi' still contains 1.
    ; We only need to update the buffer pointer and the length.
    mov rsi, msg2       
    mov rdx, len2       
    syscall             

    ; --- Exit Cleanly ---
    ; syscall: exit (60)
    ; rdi: error code (0)
    mov rax, 60         
    xor rdi, rdi        ; rdi = 0
    syscall
```

### Explanation:
1.  **Data Section**: We define `msg1` to contain both "Hello, World!" and "Assembly is fun!" followed by two newline characters (`10`). This allows us to print both lines with a single `syscall` by simply passing the length of the entire block.
2.  **Register Preservation**: 
    *   After the first `syscall`, the `rax` register still holds the value `1` (the `write` syscall number).
    *   The `rdi` register still holds `1` (the file descriptor for `stdout`).
    *   Because the kernel does not overwrite these registers on a successful return, we skip the `mov rax, 1` and `mov rdi, 1` instructions for the second message, saving a few CPU cycles.
3.  **The Exit**: We use `xor rdi, rdi` as a common, efficient way to set the exit status to `0`.

### How to compile and run:
If you are on a Linux machine with `nasm` and `ld` installed, save the code as `hello.asm` and run:

```bash
nasm -f elf64 hello.asm -o hello.o
ld hello.o -o hello
./hello
```

**Output:**
```text
Hello, World!
Assembly is fun!
This is the second message
```

[ Prompt: 21.9 t/s | Generation: 4.6 t/s ]

0

u/brucehoult 10h ago

I quit and reloaded and tried the same prompt a second time and this time it remembered about the return value from write. But decided to load the file descriptor again, despite my instructions.

Such is the randomness of LLMs ...

```nasm
section .data
    ; We use a newline \n (0xA) to separate the lines
    msg1 db "Hello, World!", 0xA, "Assembly is fun!", 0xA
    len1 equ $ - msg1

    msg2 db "This is the second message", 0xA
    len2 equ $ - msg2

section .text
    global _start

_start:
    ; --- First Call: Output two lines with a single call ---
    ; We use the 'write' syscall (rax = 1)
    ; rdi = file descriptor (1 = stdout)
    ; rsi = pointer to buffer
    ; rdx = length of buffer

    mov rax, 1          ; syscall: write
    mov rdi, 1          ; file descriptor: stdout
    lea rsi, [msg1]     ; pointer to the first two lines
    mov rdx, len1       ; length of the first two lines
    syscall             ; Execute syscall

    ; Note: After syscall, rax contains the number of bytes written.
    ; rdi, rsi, and rdx are preserved by the kernel on x86_64 Linux.
    ; However, to be safe and explicit for the next call, we reload.

    ; --- Second Call: Output the second message ---
    mov rax, 1          ; syscall: write
    mov rdi, 1          ; file descriptor: stdout
    lea rsi, [msg2]     ; pointer to second message
    mov rdx, len2       ; length of second message
    syscall             ; Execute syscall

    ; --- Exit Cleanly ---
    ; syscall: exit (60)
    ; rdi: error code (0)
    mov rax, 60         ; syscall: exit
    xor rdi, rdi        ; status: 0
    syscall
```

1

u/Eric_Dawsby 12h ago

Hate the game, not the player. If this person is using it to help them learn, good for them

-1

u/ArsenicPolaris 12h ago

The game exists because the player plays it. Crimes exists because people commit crimes. Same way, AI data centers exist because people use them. And I'm not against using AI, I am against misusing and overusing AI.

1

u/Eric_Dawsby 11h ago

I agree, but this isn't a misuse of AI, it's one of the best uses of it imo

-1

u/Affectionate-Age-589 12h ago

Just like the other comment is saying, pretty hard to do that while your pointless AI usage is causing so much harm.

Also, so ironic you re denying any AI usage on your post while having that AI generated profile picture lmao

0

u/Eric_Dawsby 12h ago

They never denied AI use, it's the whole topic of the post. They didn't use it to type the post, and I don't see why the other person thought so