Author Topic: Large Sum, up to 60 digit numbers  (Read 7920 times)

Offline encryptor256

  • Full Member
  • **
  • Posts: 250
  • Country: lv
  • Win64 .
    • On Youtube: encryptor256
Large Sum, up to 60 digit numbers
« on: July 26, 2013, 11:23:21 AM »
Hello!

This is Large Sum, up to 60 digit numbers.

Created with NASM, using GCC functions for file functions and printout.

So,
712398213456132 + 963789416284560 = 1676187629740692.

Numbers are stored in files: number1.txt, number2.txt, result.txt.

Both number files:
  • Could not exceed 60 digits
  • Must contain at least one digit

If you need more than 60 digits, like 90,
then change every number 6, in the files, to 9, then it should work.
There are no bounds, infinity, you can have sum of 1000 digits too.

For "infinity" is responsible recursive function fragment -> sumDecimalDigits, who doesn't cares how much
digits you have, just keep them coming. :)

.How_to:

Put one number in number1.txt file,
other number in number2.txt file,
run program,
get result in result.txt file.

.Program_structure:

  • largesum.asm
  • sumDecimalDigits.asm
  • bufferFunctions.asm
  • addDecimalNumbers.asm
  • fileFunctions.asm

Main compile file is "largesum.asm",
all others are just include files.



Create file named "largesum.asm", and put there following code:

Code: [Select]
[bits 32]

segment .data use32
fileName0: db "number1.txt",0
fileName1: db "number2.txt",0
fileNameR: db "result.txt",0
fileAccessRead: db "rb",0
fileAccessWrite: db "wb+",0

text_error_openfile: db "Error: cannot open file => [%s]",0

segment .bss use32
fileBuffer0: resb 61 ; Null terminated buffer
fileBuffer1: resb 61 ; Null terminated buffer
fileBufferR: resb 62 ; Null terminated buffer

segment .text use32

global _main
extern _printf
extern _scanf
extern _fopen
extern _fread
extern _fwrite
extern _fclose

; --------------------------------------------------------------------------------------------

_main:
push ebp
mov ebp,esp

push dword 61
push dword fileBuffer0
call initNumBuffer ; Inits buffer to '0' for each byte, and at the end puts zero

push dword 61
push dword fileBuffer1
call initNumBuffer ; Inits buffer to '0' for each byte, and at the end puts zero

push dword 62
push dword fileBufferR
call initNumBuffer ; Inits buffer to '0' for each byte, and at the end puts zero

; Read file 1 ----------------------------------------

push dword 60
push dword fileBuffer0
push dword fileAccessRead
push dword fileName0
call readFile

; Swap bytes, from left to right
push eax ; eax comes from readFile, bytesRead
push dword fileBuffer0
call changeBuffer

; Read file 2 ----------------------------------------

push dword 60
push dword fileBuffer1
push dword fileAccessRead
push dword fileName1
call readFile

; Swap bytes, from left to right
push eax ; eax comes from readFile, bytesRead
push dword fileBuffer1
call changeBuffer


; Calculate sum -------------------------
push dword fileBufferR
push dword fileBuffer1
push dword fileBuffer0
call addDecimalNumbers

; Swap bytes, from left to right
push dword 61
push dword fileBufferR
call changeBuffer


; Small experimental hack, to remove unneeded zeroes from result buffer
jmp removeUnusedZeroesFromResultBuffer
.callBackFromBelow:

; Write to file
;push dword 61
;push dword fileBufferR
push dword fileAccessWrite
push dword fileNameR
call writeFile

mov esp,ebp
pop ebp
mov eax,0
ret

; --------------------------------------------------------------------------------------------

%include "addDecimalNumbers.asm"
%include "sumDecimalDigits.asm"
%include "bufferFunctions.asm"
%include "fileFunctions.asm"

; --------------------------------------------------------------------------------------------

removeUnusedZeroesFromResultBuffer:

mov ecx,dword 61
mov edi,dword fileBufferR

.myLoop:

cmp [edi],byte 48 ; 48 = '0'
jne .quitMyLoop

add edi,dword 1
sub ecx,dword 1

jmp .myLoop
.quitMyLoop:

push ecx
push edi
jmp _main.callBackFromBelow

; --------------------------------------------------------------------------------------------

Create file named "sumDecimalDigits.asm", and put there following code:

Code: [Select]

; --------------------------------------------------------------------------------------------

sumDecimalDigits:
; Param 1: Digit one (0-9)
; Param 2: Digit two (0-9)
; Param 3: Carry (0-1)
; Out 1: ebx => sum
; Out 2: edx => carry
push ebp
mov ebp,esp
;---------------------------------
%define ebp_digit_one ebp+8
%define ebp_digit_two ebp+12
%define ebp_carry ebp+16
;------------------------------------
push ecx
;------------------------------------
mov edx,dword 0
mov ebx,dword [ebp_digit_one]
add ebx,dword [ebp_digit_two]
add ebx,dword [ebp_carry]
;------------------------------------
cmp ebx,10
jl .noCarry

sub ebx,10
mov edx,dword 1

.noCarry:

;---------------------------------
pop ecx
;---------------------------------
mov esp,ebp
pop ebp
;---------------------------------
ret 12

Create file named "bufferFunctions.asm", and put there following code:

Code: [Select]

; --------------------------------------------------------------------------------------------

setBufferByte:
; Param 1: Buffer address
; Param 2: Byte index
; Param 2: Byte value
; Out: eax = 0
push ebp
mov ebp,esp
;---------------------------------
%define ebp_buffer_address ebp+8
%define ebp_byte_index ebp+12
%define ebp_byte_value ebp+16
;------------------------------------
push edi
push ecx
push ebx
push edx
;------------------------------------
mov eax,dword [ebp_byte_value]
mov edi,dword [ebp_buffer_address]
add edi,dword [ebp_byte_index]
mov byte [edi], al
;---------------------------------
pop edx
pop ebx
pop ecx
pop edi
;---------------------------------
mov esp,ebp
pop ebp
;---------------------------------
mov eax,0
ret 12

; --------------------------------------------------------------------------------------------

getBufferByte:
; Param 1: Buffer address
; Param 2: Byte index
; Out: eax => al = byte value
push ebp
mov ebp,esp
;---------------------------------
%define ebp_buffer_address ebp+8
%define ebp_byte_index ebp+12
;------------------------------------
push edi
push ecx
;------------------------------------
mov edi,dword [ebp_buffer_address]
add edi,dword [ebp_byte_index]
xor eax,eax
mov al,byte [edi]
;---------------------------------
pop ecx
pop edi
;---------------------------------
mov esp,ebp
pop ebp
;---------------------------------
ret 8

; --------------------------------------------------------------------------------------------

changeBuffer:
push ebp
mov ebp,esp
;---------------------------------
%define ebp_buffer_address ebp+8
%define ebp_buffer_len ebp+12
%define ebp_loop_times ebp-4
;---------------------------------
sub esp,dword 4
pushad
pushfd
;---------------------------------
mov eax,dword [ebp_buffer_len]
mov edx,0
mov ebx,2
div ebx
mov dword [ebp_loop_times],eax
;---------------------------------
mov esi,dword [ebp_buffer_address]
mov edi,dword [ebp_buffer_address]
add edi,dword [ebp_buffer_len]
sub edi,dword 1
.inLoop:
mov al,[esi]
mov ah,[edi]
mov [esi],ah
mov [edi],al
add esi,1
sub edi,1
;---------------------------------
mov eax,dword [ebp_loop_times]
sub eax,dword 1
mov dword [ebp_loop_times],eax
cmp eax,dword 0
jne .inLoop
;---------------------------------
popfd
popad
add esp,4
;---------------------------------
mov esp,ebp
pop ebp
;---------------------------------
ret 8

; --------------------------------------------------------------------------------------------

initNumBuffer:
push ebp
mov ebp,esp
;---------------------------------
%define ebp_buffer_address ebp+8
%define ebp_buffer_len ebp+12
;---------------------------------
mov edi,dword [ebp_buffer_address]
mov ecx,0
.doLoop:
mov [edi],byte '0'
add edi,dword 1
add ecx,dword 1
cmp ecx,dword [ebp_buffer_len]
jne .doLoop
;---------------------------------
sub edi,dword 1
mov [edi],byte 0
;---------------------------------
mov esp,ebp
pop ebp
;---------------------------------
ret 8

Create file named "addDecimalNumbers.asm", and put there following code:

Code: [Select]

; --------------------------------------------------------------------------------------------

addDecimalNumbers:
; Param 1: num1 buffer address (IN)
; Param 2: num2 buffer address (IN)
; Param 3: result buffer address (IN_OUT)
push ebp
mov ebp,esp
;---------------------------------
%define ebp_num1 ebp+8
%define ebp_num2 ebp+12
%define ebp_result ebp+16
;------------------------------------
mov ecx,dword 0
.inLoop:

; Prepare parameters for sumDecimalDigits, byte from each buffer
push ecx
push dword [ebp_result]
call getBufferByte
sub eax,dword 48 ; Each digit is ascii, so, by sub 48 we get decimal number
push eax

push ecx
push dword [ebp_num2]
call getBufferByte
cmp eax,dword 0
je .breakLoop
sub eax,dword 48 ; Each digit is ascii, so, by sub 48 we get decimal number
push eax

push ecx
push dword [ebp_num1] ; Each digit is ascii, so, by sub 48 we get decimal number
call getBufferByte
cmp eax,dword 0
je .breakLoop
sub eax,dword 48
push eax

call sumDecimalDigits

; Set sum
add ebx,dword 48
push ebx
push ecx
push dword [ebp_result]
call setBufferByte

;---------------------------------
add ecx,dword 1

; Set Carry
add edx,dword 48
push edx
push ecx
push dword [ebp_result]
call setBufferByte

;---------------------------------
cmp ecx,dword 99999
jle .inLoop

.breakLoop:
;---------------------------------
mov esp,ebp
pop ebp
;---------------------------------
mov eax,0
ret 12

Create file named "fileFunctions.asm", and put there following code:

Code: [Select]

; --------------------------------------------------------------------------------------------

readFile:
push ebp
mov ebp,esp
;------------------------------
%define ebp_filename ebp+8
%define ebp_fileaccess ebp+12
%define ebp_buffer ebp+16
%define ebp_buffer_len ebp+20
;------------------------------
%define ebp_filehandle ebp-4
sub esp,dword 4
;------------------------------

push dword [ebp_fileaccess]
push dword [ebp_filename]
call _fopen
add esp,8

mov dword [ebp_filehandle],eax
cmp eax,dword 0
jne .openSuccess


push dword [ebp_filename]
push dword text_error_openfile
call _printf
add esp,8
mov eax,dword 0
jmp .quitFunction

.openSuccess:

push dword [ebp_filehandle]
push dword [ebp_buffer_len]
push dword 1
push dword [ebp_buffer]
call _fread
add esp,16

push eax

push dword [ebp_filehandle]
call _fclose
add esp,4

pop eax

.quitFunction:
mov esp,ebp
pop ebp
ret 16

; --------------------------------------------------------------------------------------------

writeFile:
push ebp
mov ebp,esp
;------------------------------
%define ebp_filename ebp+8
%define ebp_fileaccess ebp+12
%define ebp_buffer ebp+16
%define ebp_buffer_len ebp+20
;------------------------------
%define ebp_filehandle ebp-4
sub esp,dword 4
;------------------------------

push dword [ebp_fileaccess]
push dword [ebp_filename]
call _fopen
add esp,8

mov dword [ebp_filehandle],eax
cmp eax,dword 0
jne .openSuccess


push dword [ebp_filename]
push dword text_error_openfile
call _printf
add esp,8
mov eax,dword 0
jmp .quitFunction

.openSuccess:

push dword [ebp_filehandle]
push dword [ebp_buffer_len]
push dword 1
push dword [ebp_buffer]
call _fwrite
add esp,16

push eax

push dword [ebp_filehandle]
call _fclose
add esp,4

pop eax

.quitFunction:
mov esp,ebp
pop ebp
ret 16



Registers ESI and EDI, can be used to access bytes in the buffers, cool!

.Produce_exe_file:

Put all files in the same directory, and execute following command prompt commands:

Code: [Select]

NASM cmd: "nasm.exe -f win32 -o largesum.o largesum.asm"

GCC cmd: "gcc -m32 -o largesum.exe largesum.o"


If you use SciTE code editor,
then you can alter asm property configuration file,
and put or change lines, like this:

Code: [Select]

command.compile.$(file.patterns.asm)=K:\nasm\nasm.exe -f win32 -o $(FileName).o $(FileNameExt)

command.0.*.asm=L:\Dev-Cpp\MinGW32\bin\gcc -m32 -o $(FileName).exe $(FileName).o




Attachment includes program structure files.

Bye, Encryptor256.

.Edit:

There is one another purpose,
you can solve ProjectEuler's Problem 13,
there you have to sum 100 x 50digit numbers. :)

Now im making new version to do this automaticaly.
« Last Edit: July 26, 2013, 02:08:30 PM by encryptor256 »
Encryptor256's Investigation \ Research Department.