Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- section .text
- global start
- %define argOne rdi
- %define argSec rsi
- %define numShort rbx
- %define size rcx
- %define Result rdx
- %define copyNum rbp
- %define curPtrStack rsp
- start:
- sub curPtrStack, 4 * 128 * 8 ; reserve memory for stack
- lea argOne, [curPtrStack + 128 * 8] ;lea moves adress of the argSec operand to the argOne. x = [sp + 128 * 8]
- mov size, 128; select size
- call read_long ;argOne arg -> rdi
- mov argOne, curPtrStack ;in argOne now adress of the begining of the argOne number
- call read_long ;reads argSec number to rsi
- lea argSec, [curPtrStack + 128 * 8] ;in argSec adress of the begining of the argOne number
- lea copyNum, [argSec + 128 * 8] ;copyNum memory for the
- lea Result, [copyNum + 128 * 8] ;result memory
- call mul_long_long
- mov argOne, Result
- call write_long
- mov rax, 0x0a
- call write_char
- jmp exit
- mul_long_long:
- push argSec
- push size
- push argOne
- push Result
- push copyNum
- push rax
- push rdx
- mov rax, argOne
- mov argOne, Result
- call set_zero
- mov argOne, rax ; result = 0
- clc
- .loop: ;loop will be done (size) times
- call array_copy ; copyNum = copy of argOne
- mov numShort, [argSec] ; c = argSec[i]
- call mul_long_short ; argOne *= c
- mov rax, argSec ; rax = argSec
- mov argSec, argOne ; argSec = argOne
- mov argOne, Result ; argOne = Result
- call add_long_long ; argOne += argSec
- ;Result += argOneNumber * c * (2^64)^i
- mov argOne, argSec ; argOne = argSec
- mov argSec, rax ; argSec = rax
- lea argSec, [argSec + 8] ; argSec[i] -> argSec[i + 1]
- xchg copyNum, argOne ; swap(argOne, copyNum)
- call array_copy ; copyNum = argOne
- xchg copyNum, argOne ; swap(argOne, copyNum)
- call shift_left ; array(argOne) *= 2^64
- dec size ; i -> i++
- jnz .loop ; while size > 0
- pop rdx
- pop rax
- pop copyNum
- pop Result
- pop argOne
- pop size
- pop argSec
- ret
- array_copy: ;copies argOne to copyNum
- push argOne
- push copyNum
- push size
- push rax
- mov size, 128
- .loop:
- mov rax, [argOne]
- mov [copyNum], rax ; moves from argOne to copyNum
- add argOne, 8
- add copyNum, 8 ; argOne[i] -> argOne[i + 1], copyNum[i] -> copyNum[i + 1]
- dec size ; loop will be done 128 times, for each i: 1..128
- jnz .loop
- pop rax
- pop size
- pop copyNum
- pop argOne
- ret
- shift_left: ;argOne *= 2^64, [x128, x127, ..., x1] -> [x127, x126, ..., 0]
- push argOne
- push size
- push rax
- push rbx
- mov size, 127
- lea argOne, [argOne + 127 * 8] ;start moving from the 127th element
- .loop:
- mov rax, argOne
- sub argOne, 8
- mov rbx, [argOne]
- mov [rax], rbx ;argOne[i] = argOne[i - 1]
- dec size ;cicle will bo done 127 times, argOne[128] will be lost
- jnz .loop
- mov rax, 0
- mov [argOne], rax ;argOne[1] = 0
- pop rbx
- pop rax
- pop size
- pop argOne
- ret
- add_long_long: ;argOne += argSec
- push argOne
- push argSec
- push size
- push rax
- mov size, 128
- clc
- .loop:
- mov rax, [argSec]
- adc [argOne], rax ;adding with carry flag, argOne[i] += argSec[i]
- lea argOne, [argOne + 8] ;argOne[i] -> argOne[i + 1]
- lea argSec, [argSec + 8] ;argSec[i] -> argSec[i + 1]
- dec size ;cycle will be done 128 times, for each i: 1..128
- jnz .loop
- pop rax
- pop size
- pop argSec
- pop argOne
- ret
- ; adds 64-bit number to long number
- ; rdi -- address of summand #1 (long number)
- ; rax -- summand #2 (64-bit unsigned)
- ; rcx -- length of long number in qwords
- ; result:
- ; sum is written to rdi
- add_long_short:
- push argOne
- push size
- push Result
- clc
- xor rdx, rdx
- .loop:
- add [argOne], rax ;argOne[i] += x
- adc rdx, 0 ;rdx = carry
- mov rax, rdx ;x = carry
- xor rdx, rdx ;carry = 0
- add argOne, 8 ;argOne[i] -> argOne[i + 1]
- dec rcx
- jnz .loop
- pop Result
- pop size
- pop argOne
- ret
- ; multiplies long number by a short
- ; rdi -- address of multiplier #1 (long number)
- ; rbx -- multiplier #2 (64-bit unsigned)
- ; rcx -- length of long number in qwords
- ; result:
- ; product is written to rdi
- mul_long_short:
- push rax
- push argOne
- push size
- push argSec
- push numShort
- push Result
- clc
- mov size, 128
- mov rsi, 0
- .loop:
- mov rax, [argOne] ; rsi - carry
- mul numShort ; rdx:rax = rax * numShort, rdx will be used as carry the next time
- add rax, rsi ; rax += rsi, pluses carry, makes CarryFlag
- adc rdx, 0 ; rdx += CarryFlag
- mov [argOne], rax ; argOne[i] = rax
- add argOne, 8 ; argOne[i] -> argOne[i + 1]
- mov rsi, rdx ; rsi = rdx, updates carry
- dec size
- jnz .loop
- pop Result
- pop numShort
- pop argSec
- pop size
- pop argOne
- pop rax
- ret
- ; divides long number by a short
- ; rdi -- address of dividend (long number)
- ; rbx -- divisor (64-bit unsigned)
- ; rcx -- length of long number in qwords
- ; result:
- ; quotient is written to rdi
- ; rdx -- remainder
- div_long_short:
- push rdi
- push rax
- push rcx
- push rbx
- clc
- lea rdi, [rdi + 8 * rcx - 8]
- xor rdx, rdx
- .loop:
- mov rax, [rdi]
- div rbx
- mov [rdi], rax
- sub rdi, 8
- dec rcx
- jnz .loop
- pop rbx
- pop rcx
- pop rax
- pop rdi
- ret
- ; assigns a zero to long number
- ; rdi -- argument (long number)
- ; rcx -- length of long number in qwords
- set_zero:
- push rax
- push rdi
- push rcx
- push rax
- xor rax, rax
- rep stosq
- pop rax
- pop rcx
- pop rdi
- pop rax
- ret
- ; checks if a long number is a zero
- ; rdi -- argument (long number)
- ; rcx -- length of long number in qwords
- ; result:
- ; ZF=1 if zero
- is_zero:
- push rax
- push rdi
- push rcx
- push rax
- xor rax, rax
- rep scasq
- pop rax
- pop rcx
- pop rdi
- pop rax
- ret
- ; read long number from stdin
- ; rdi -- location for output (long number)
- ; rcx -- length of long number in qwords
- read_long:
- push rcx
- push rdi
- push rax
- call set_zero
- .loop:
- call read_char
- or rax, rax
- js exit
- cmp rax, 0x0a
- je .done
- cmp rax, '0'
- jb .invalid_char
- cmp rax, '9'
- ja .invalid_char
- sub rax, '0'
- mov rbx, 10
- call mul_long_short
- call add_long_short
- jmp .loop
- .done:
- pop rax
- pop rdi
- pop rcx
- ret
- .invalid_char:
- mov rsi, invalid_char_msg
- mov rdx, invalid_char_msg_size
- call print_string
- call write_char
- mov al, 0x0a
- call write_char
- .skip_loop:
- call read_char
- or rax, rax
- js exit
- cmp rax, 0x0a
- je exit
- jmp .skip_loop
- ; write long number to stdout
- ; rdi -- argument (long number)
- ; rcx -- length of long number in qwords
- write_long:
- push rax
- push rcx
- push rbp
- push rsi
- push rbx
- push rdx
- push curPtrStack
- mov rax, 20
- mul rcx
- mov rbp, curPtrStack
- sub curPtrStack, rax
- mov rsi, rbp
- .loop:
- mov rbx, 10
- call div_long_short
- add rdx, '0'
- dec rsi
- mov [rsi], dl
- call is_zero
- jnz .loop
- mov rdx, rbp
- sub rdx, rsi
- call print_string
- mov curPtrStack, rbp
- pop curPtrStack
- pop rdx
- pop rbx
- pop rsi
- pop rbp
- pop rcx
- pop rax
- ret
- ; read one char from stdin
- ; result:
- ; rax == -1 if error occurs
- ; rax \in [0; 255] if OK
- read_char:
- push rcx
- push rdi
- sub rsp, 1
- mov rax, 0x2000003 ;
- xor rdi, rdi
- mov rsi, rsp
- mov rdx, 1
- syscall
- cmp rax, 1
- jne .error
- xor rax, rax
- mov al, [rsp]
- add rsp, 1
- pop rdi
- pop rcx
- ret
- .error:
- mov rax, -1
- add rsp, 1
- pop rdi
- pop rcx
- ret
- ; write one char to stdout, errors are ignored
- ; al -- char
- write_char:
- sub rsp, 1
- mov [rsp], al
- mov rax, 0x2000004
- mov rdi, 1
- mov rsi, rsp
- mov rdx, 1
- syscall
- add rsp, 1
- ret
- exit:
- mov rax, 0x2000001
- xor rdi, rdi
- syscall
- ; print string to stdout
- ; rsi -- string
- ; rdx -- size
- print_string:
- push rax
- push rdi
- mov rax, 0x2000004
- mov rdi, 1
- syscall
- pop rdi
- pop rax
- ret
- section .rodata
- invalid_char_msg:
- db "Invalid character: "
- invalid_char_msg_size: equ $ - invalid_char_msg
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement