Assignment 1
Leap Year
Task: Design and write an assembly code that will determine if a given year is a Leap Year.
Things to consider
● How to change a string of numbers into its numerical counterpart
o Helpful Hit:
▪ Take a 4-digit string
▪ Get the thousands digit
▪ Multiply by 10
▪ Add the hundred’s digit
▪ Multiply by 10
▪ etc.….
● What defines a leap year
A year is a leap year if it is divisible by 4 and not divisible by 100, unless it is also
divisible by 400.
● Would any loops (jmp to self), or if else statements (je or jne) that would be useful
Loop:
~~~~
Code
~~~~
jmp Loop
Compares:
cmp ~x~, ~y~
je ~~something~~
jne ~~something else~~
Solution
lab4.asm
; lab4.asm Design? ?and? ?write? ?an? ?assembly? ?code? ?that? ?will? ?determine? ?if? ?a? ?given? ?year? ?is? ?a? ?Leap? ?Year
;
; compile: nasm -f elf64 -l lab4.lst lab4.asm
; ld -o lab4 lab4.o
; run: ./lab4
SECTION .data ; data section
question:
db “Type year:”,10 ; the string to print, 10=cr
len: equ $-question ; “$” means “here”
; len is a value, not an address
fourhundred:
dq 400
hundred:
dq 100
four:
dq 4
message: db “This year is a leapyear”, 10, 0 ; the string to print, 10=cr
message.length: equ $-message
message1: db “This year is not a leapyear”, 10, 0 ; the string to print, 10=cr
message1.length: equ $-message1
error: db “Error”, 10, 0 ; the string to print, 10=cr
error.length: equ $-error
SECTION .bss
inp_buf resb 256
SECTION .text ; code section
global _start
section .text
_start:
mov edx,len ; arg3, length of string to print
mov ecx,question ; arg2, pointer to string
mov ebx,1 ; arg1, where to write, screen
mov eax,4 ; write sysout command to int 80 hex
int 0x80 ; interrupt 80 hex, call kernel
mov eax,3 ;sys_read. Read what user inputs
mov ebx,0 ;From stdin
mov ecx,inp_buf ;Save user input to buffer.
int 80h
xor rax, rax ; clear rax
lea rsi,[inp_buf]
lea rdi,[inp_buf]
mov rcx,4
call string_to_int
; RAX now contains year number
push rax ; save year
xor rdx, rdx ; clear
div qword [fourhundred] ; mod year by 400
cmp rdx, 0
jz printLeapYear ; if divisible by 400 it is a leap year
pop rax ; load year
push rax ; save year
xor rdx, rdx
div qword [hundred] ; divide year by 100
cmp rdx, 0
jz printNoLeapYear ; if divisible 100 it is not a leap year
pop rax ; load year
push rax ; save year
xor rdx, rdx
div qword [four] ; divide year by 4
cmp rdx, 0
jz printLeapYear ; if divisible by 4 it is a leap year
jnz printNoLeapYear ; else it is not a leap year
jmp exit
printLeapYear:
pop rax
mov rsi, message
mov rdx, message.length
xor rax, rax
mov rax, 1 ; system call 1 is write
mov rdi, 1 ; file handle 1 is stdout
syscall
jmp exit
printNoLeapYear:
pop rax
mov rsi, message1
mov rdx, message1.length
xor rax, rax
mov rax, 1 ; system call 1 is write
mov rdi, 1 ; file handle 1 is stdout
syscall
jmp exit
printError:
;pop rax
;mov rsi, rax
mov rsi, error
mov rdx, error.length
;xor rax, rax
mov rax, 1 ; system call 1 is write
mov rdi, 1 ; file handle 1 is stdout
syscall
jmp exit
exit:
mov eax, 60 ; system call 60 is exit
xor rdi, rdi ; exit code 0
syscall
; Input:
; RSI = pointer to the string to convert
; RCX = number of digits in the string (must be > 0)
; Output:
; RAX = integer value
string_to_int:
xor rbx,rbx ; clear rbx
.next_digit:
movzx rax,byte[rsi]
inc rsi
sub al,’0′ ; convert from ASCII to number
imul rbx,10
add rbx,rax ; rbx = rbx*10 + rax
loop .next_digit ; while (–rcx)
mov rax,rbx
ret