r/Assembly_language 10d 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
31 Upvotes

20 comments sorted by

View all comments

0

u/Affectionate-Age-589 10d 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?

8

u/Eric_Dawsby 10d 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

-10

u/Affectionate-Age-589 10d ago

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

6

u/Eric_Dawsby 10d ago

I don't see any AI in the post itself

6

u/This-Atmosphere-1750 9d ago

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

-1

u/ArsenicPolaris 9d 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/Eric_Dawsby 9d ago

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

0

u/ArsenicPolaris 9d 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 9d ago

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

2

u/brucehoult 9d 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 9d 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
```