.text
.globl _start
_start:
#write(1, QUESTION, sizeof(QUESTION) - 1);
mov $1, %rdi #stdout fileno
lea question, %rsi #pointer to string
mov $question_len, %rdx #length
mov $1, %rax #no. for write
syscall #do it!
cmp $0, %rax #check return value
jl error #if negative, error out
#read(0, buffer, sizeof(buffer));
mov $0, %rdi #stdin fileno
lea buffer, %rsi #pointer to buffer
mov $buffer_len, %rdx #length
mov $0, %rax #no. for read
syscall #do it!
push %rax #save return value
cmp $1, %rax #check return value
jle error #if <= 1, error out
#write(1, MESSAGE, sizeof(MESSAGE) - 1);
mov $1, %rdi #stdout fileno
lea hellomsg, %rsi #pointer to string
mov $hello_len, %rdx #length
mov $1, %rax #no. for write
syscall #do it!
cmp $0, %rax #check return value
jl error #if negative, error out
#write(1, buffer, (size_t)len);
mov $1, %rdi #stdout fileno
lea buffer, %rsi #pointer to buffer
pop %rdx #saved length
mov $1, %rax #no. for write
syscall #do it!
cmp $0, %rax #check return value
jl error #if <= 1, error out
mov $0, %rdi #exit status of 0
mov $60, %rax #no. for exit
syscall #do it!
error:
mov $2, %rdi #stderr fileno
lea errormsg, %rsi #pointer to string
mov $error_len, %rdx #length
mov $1, %rax #no. for write
syscall #do it!
mov $1, %rdi #exit status of 1
mov $60, %rax #no. for exit
syscall #do it!
.data
question:
.ascii "What is your name?\n"
.equ question_len, . - question
errormsg:
.ascii "error!\n"
.equ error_len, . - errormsg
buffer:
.equ buffer_len, 100
.space buffer_len, 0
hellomsg:
.ascii "Hello, "
.equ hello_len, . - hellomsg
#include <syscall.h>
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
.globl _start //make _start a global symbol so linker can find it
_start: //_start is entry point for all executibles
mov %rax, $SYS_write //%rax holds syscall number, 1 represents `write`
mov %rdi, $STDOUT_FILENO //%rdi holds first syscall arg, 1 represents `stdout`
lea %rsi, prompt //%rsi holds second arg, =prompt gets address if prompt string from data section
mov %rdx, $prompt_len //%rdx holds third arg, prompt_len is macro that expands to calculated size
syscall //perform a system call
cmp %rdi, $0 //check if return is negative
jl .out //if it is, exit program early with exit code based on return value
mov %rax, $SYS_read //0 represents `read`
mov %rdi, $STDIN_FILENO //0 represents `stdin`
ldr %rsi, =buffer //read into buffer
mov %rdx, $buffer_len //at most buffer_len bytes
syscall //perform syscall
cmp %rdi, $0 //check for error as above
jl .out
mov %rcx, %rdi //save returned length to only print that many bytes
mov %rax, $SYS_write //back to writing, send "Hello, " to stdout
mov %rdi, $STDOUT_FILENO
ldr %rsi, =msg
mov %rdx, $msg_len
syscall
cmp %rdi, $0 //check for error
jl .out
mov %rdi, $1 //need to set %rdi back to 1 because it was replaced with return code of last call
ldr %rsi, =buffer //whatever they input
mov %rdx, %rcx //and however long it was
syscall //send that
cmp %rdi, $0 //check for errors
jl .out
mov %rdi, $0 //if there was not an error, set return code to 0
.out: //otherwise we were sent here and %rdi already contains error code to return
mov %rax, $SYS_exit //60 represents exit
syscall //exit program
//exit syscall does not return, so _start function does not need to return to caller
.data //data section for strings
prompt: .ascii "What is your name? "
.equ prompt_len, .-prompt //.equ makes a new macro, `.` represents current location in binary, and subtracting the value of prompt gives how many bytes prompt contained
buffer: .space 64
.equ buffer_len, .-buffer
msg: .ascii "Hello, "
.equ msg_len, .-msg
.data
message:
.ascii "Hello, World!\n"
len = . - message
.text
.global _start
_start:
mov $1, %rdi
mov $message, %rsi
mov $len, %rdx
mov $1, %rax
syscall
mov $13, %rdi
mov $60, %rax
syscall
#include <syscall.h>
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
.globl _start //make _start a global symbol so linker can find it
_start: //_start is entry point for all executibles
mov x8, #SYS_write //x8 holds syscall number, 64 represents `write`
mov x0, #STDOUT_FILENO //x0 holds first syscall arg, 1 represents `stdout`
ldr x1, =prompt //x1 holds second arg, =prompt gets address if prompt string from data section
mov x2, #prompt_len //x2 holds third arg, prompt_len is macro that expands to calculated size
svc #0 //perform a system call
cmp x0, #0 //check if return is negative
b.lt .out //if it is, exit program early with exit code based on return value
mov x8, #SYS_read //63 represents `read`
mov x0, #STDIN_FILENO //0 represents `stdin`
ldr x1, =buffer //read into buffer
mov x2, #buffer_len //at most buffer_len bytes
svc #0 //perform syscall
cmp x0, #0 //check for error as above
b.lt .out
mov x3, x0 //save returned length to only print that many bytes
mov x8, #SYS_write //back to writing, send "Hello, " to stdout
mov x0, #STDOUT_FILENO
ldr x1, =msg
mov x2, #msg_len
svc #0
cmp x0, #0 //check for error
b.lt .out
mov x0, #1 //need to set x0 back to 1 because it was replaced with return code of last call
ldr x1, =buffer //whatever they input
mov x2, x3 //and however long it was
svc #0 //send that
cmp x0, #0 //check for errors
b.lt .out
mov x0, #0 //if there was not an error, set return code to 0
.out: //otherwise we were sent here and x0 already contains error code to return
mov x8, #SYS_exit //93 represents exit
svc #0 //exit program
//exit syscall does not return, so _start function does not need to return to caller
.data //data section for strings
prompt: .ascii "What is your name? "
.equ prompt_len, .-prompt //.equ makes a new macro, `.` represents current location in binary, and subtracting the value of prompt gives how many bytes prompt contained
buffer: .space 64
.equ buffer_len, .-buffer
msg: .ascii "Hello, "
.equ msg_len, .-msg
.PHONY: all clean
all:asm_hello
asm_hello: asm_hello.o
ld -o asm_hello asm_hello.o
asm_hello.o: asm_hello.s
as asm_hello.s -o asm_hello.o
asm_hello.s: asm_hello.S
cpp asm_hello.S -o asm_hello.s
clean:
-rm asm_hello.s asm_hello.o asm_hello