x86 Is it a leap year

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