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_bufresb 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
movecx,inp_buf ;Save user input to buffer.
int 80h
xorrax, rax ; clear rax
learsi,[inp_buf]
leardi,[inp_buf]
mov rcx,4
callstring_to_int
; RAX now contains year number
pushrax ; save year
xorrdx, rdx ; clear
div qword [fourhundred] ; mod year by 400
cmprdx, 0
jzprintLeapYear ; if divisible by 400 it is a leap year
poprax ; load year
pushrax ; save year
xorrdx, rdx
div qword [hundred] ; divide year by 100
cmprdx, 0
jzprintNoLeapYear ; if divisible 100 it is not a leap year
poprax ; load year
pushrax ; save year
xorrdx, rdx
div qword [four] ; divide year by 4
cmprdx, 0
jzprintLeapYear ; if divisible by 4 it is a leap year
jnzprintNoLeapYear ; else it is not a leap year
jmp exit
printLeapYear:
poprax
movrsi, message
movrdx, message.length
xorrax, rax
movrax, 1 ; system call 1 is write
movrdi, 1 ; file handle 1 is stdout
syscall
jmp exit
printNoLeapYear:
poprax
movrsi, message1
movrdx, message1.length
xorrax, rax
movrax, 1 ; system call 1 is write
movrdi, 1 ; file handle 1 is stdout
syscall
jmp exit
printError:
;poprax
;movrsi, rax
movrsi, error
movrdx, error.length
;xorrax, rax
movrax, 1 ; system call 1 is write
movrdi, 1 ; file handle 1 is stdout
syscall
jmp exit
exit:
moveax, 60 ; system call 60 is exit
xorrdi, 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:
xorrbx,rbx ; clear rbx
.next_digit:
movzxrax,byte[rsi]
incrsi
sub al,’0′ ; convert from ASCII to number
imul rbx,10
addrbx,rax ; rbx = rbx*10 + rax
loop .next_digit ; while (–rcx)
movrax,rbx
ret