#!/bin/bash
# Check if file is provided
if [ -z "$1" ]; then
echo "Usage: $0 <assembly-file>"
exit 1
fi
# Set the input file
asm_file=$1
# Get the base filename without the extension
base_filename=$(basename "$asm_file" .s)
# Assemble
# nasm -f elf64 "$asm_file" -o "$base_filename.o"
as "$asm_file" -o "$base_filename.o"
if [ $? -ne 0 ]; then
echo "Error: Assembly failed"
exit 1
fi
# Link
gcc -no-pie "$base_filename.o" -o "$base_filename.bin"
if [ $? -ne 0 ]; then
echo "Error: Linking failed"
exit 1
fi
# Execute
./"$base_filename.bin"
.text
.globl main # Make main visible for the linker
main:
pushq %rbp # Save base pointer
movq %rsp, %rbp # Set up stack frame
# Load x from memory
movq x(%rip), %rax # Move the value of x (2) into RAX
# y = x * x
imulq %rax, %rax # Multiply x by itself (RAX = RAX * RAX, now RAX = 4)
# Store the result of y in memory
movq %rax, y(%rip) # Move the result (y = 4) into the y variable
# Load x and y from memory
movq x(%rip), %rax # Load x (2) back into RAX
addq y(%rip), %rax # Add y (4) to RAX (RAX = 4 + 2 = 6)
# Prepare for the printf call
movq $result_msg, %rdi # Load the format string into RDI
movq %rax, %rsi # Move the result (6) into RSI
xorq %rax, %rax # Clear RAX for calling printf
call printf # Call printf to print the result
# Exit the program
movq $60, %rax # syscall: exit
xorq %rdi, %rdi # status: 0
syscall # invoke syscall
popq %rbp # Restore base pointer
ret # Return from main
.data # Data section
x: .quad 2 # Allocate x in the data segment, initialized to 2
y: .quad 0 # Allocate y in the data segment, initialized to 0
result_msg: .string "%d\n" # Format string for printf
.data
result_msg: .string "%d\n" # Format string for printf
.text
.globl main # Make main visible for the linker
main:
pushq %rbp # Save base pointer
movq %rsp, %rbp # Set up stack frame
### First Instruction: print (let x = 3 in x * x)
# Allocate space for x on the stack
subq $8, %rsp # Reserve 8 bytes on the stack for x
movq $3, (%rsp) # Set x = 3 (store on stack)
# x * x
movq (%rsp), %rax # Load x into RAX
imulq %rax, %rax # Multiply x by itself (RAX = x * x)
# Prepare for the printf call (result is 9)
movq $result_msg, %rdi # Load the format string into RDI
movq %rax, %rsi # Move the result (9) into RSI
xorq %rax, %rax # Clear RAX for calling printf
call printf # Call printf to print the result
# Deallocate space for x
addq $8, %rsp # Free the space allocated for x on the stack
### Second Instruction: print (let x = 3 in ...)
# Allocate space for x on the stack
subq $8, %rsp # Reserve 8 bytes on the stack for x
movq $3, (%rsp) # Set x = 3 (store on stack)
# Inner block: let y = x + x in x * y
subq $8, %rsp # Reserve 8 bytes on the stack for y
movq 8(%rsp), %rax # Load x into RAX (from previous stack slot)
addq %rax, %rax # y = x + x (RAX = x + x)
movq %rax, (%rsp) # Store y on the stack 3
movq 8(%rsp), %rax # Load x into RAX again (from previous stack slot)
imulq (%rsp), %rax # Multiply x * y (RAX = x * y)
movq %rax, (%rsp) # Store y on the stack 18
# Inner block: let z = x + 3 in z / z
subq $8, %rsp # Reserve 8 bytes on the stack for z
movq 16(%rsp), %rcx # Load x into RCX (from previous stack slot)
addq $3, %rcx # z = x + 3 (RCX = x + 3)
movq %rcx, (%rsp) # Store z on the stack
xorq %rdx, %rdx # Clear RDX (for division)
movq (%rsp), %rax # Load z into RAX (z = x + 3)
idivq %rax # z / z (RAX = z / z, which is 1)
# Compute (x * y) + (z / z)
addq %rax, 8(%rsp) # Add z / z (which is 1) to x * y (from earlier)
# Prepare for the printf call (result is 19)
movq $result_msg, %rdi # Load the format string into RDI
movq 8(%rsp), %rsi # Load the result (19) into RSI
xorq %rax, %rax # Clear RAX for calling printf
call printf # Call printf to print the result
# Deallocate space for z, y, and x
addq $24, %rsp # Free the space allocated for z, y, and x
### Exit the program
movq $60, %rax # syscall: exit
xorq %rdi, %rdi # status: 0
syscall # invoke syscall
popq %rbp # Restore base pointer
ret # Return from main
#include <stdio.h>
int isqrt(int n)
{
int c = 0, s = 1;
// x^2 = (x-1)^2 + 2(x-1) + 1
do
{
// Increment c and calculate s in one line
s += (++c << 1) + 1;
} while (s <= n); // Single branching instruction here
return c;
}
int main()
{
int n;
for (n = 0; n <= 20; n++)
printf("sqrt(%2d) = %2d\n", n, isqrt(n));
return 0;
}