Author Topic: traversing through a Register  (Read 9200 times)

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
traversing through a Register
« on: June 29, 2014, 09:35:26 PM »
I have been trying to add individual digits together in a register for example if I have a number 423 then I would add them like so : 4 + 2 + 3 = 9 but it isnt giving me the desired result when I execute this code:
Code: [Select]
mov qword[x_number], r8
mov r8, x_number;mov the adress into r8
add r8, 80
mov byte [r8], 0;put a zero after the number
sub r8, 80
xor rcx, rcx;clear out rcx for use

;add individual digits together
.forLoop2:
add cl, byte[r8]


add r8, 1;get ready for the next number

cmp byte[r8], 0;if this digit is equal not equal to zero then jump back to the top
jne .forLoop2
;print out the result stored in rcx
mov qword[x_number], rcx
mov r8, qword[x_number]
call itoa
;print out a new Line
mov rsi, newLine
mov rdx, newLine_L
mov rax, 1
mov rdi, 1
syscall

I think its is because of the way I am traversing through the register but I have no Idea how I can fix it
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: traversing through a Register
« Reply #1 on: June 29, 2014, 10:42:00 PM »
Hmmm... what have you done before the code you show?
Code: [Select]
mov r8, 432 ; decimal
mov r8, 432h ; or 0x432 or $432 - hex
mov r8, "432" ; ascii
?
None of these is going to put a digit in a byte.

Code: [Select]
mov r8, 4<<16 | 3<<8 | 2
This one might give you the result you seem to expect.

I'm confused!

Best,
Frank




Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: traversing through a Register
« Reply #2 on: June 30, 2014, 04:05:23 AM »
Well I am trying to get a number with  a power like if the user enters 2 and 15 it would turn out as 2^15 or 32768 and I have tested it to see if it works I then print the value 32768 push it onto the stack then pass it to r8 and move the actual number to it here is my number to it I didn't post the full code because i didn't think it was relevant but here it is:
Code: [Select]

section .data
PowerMsg: dq "Input a power",10
PowerMsg_L: equ $ - PowerMsg
newLine: dq "",10
  newLine_L: equ $ - newLine
section .bss
power resq 255
number resq 255
section .text

%include "functions.asm"

global _start:

_start:

mov rax, 1
mov rdi, 1
mov rdx, MSG_L
mov rsi, MSG
syscall

mov rax, 0;
mov rdi, 0
mov rdx, 255
mov rsi, number
syscall


mov rax, 1
mov rdi, 1
mov rdx, PowerMsg_L
mov rsi, PowerMsg
syscall


mov rax, 0
mov rdi, 0
mov rdx, 255
mov rsi, power
syscall


mov r8, power
call atoi

mov rcx, rax; the power
push rcx
mov r8, number
call atoi
pop rcx
call PowerSum


mov rax, 60
mov rdi, 0
syscall

ret






PowerSum:

;power is passed in rcx
;number is passed in rax

push rbx
mov rbx, rax

.forLoop:;calculates the n^x power

xor rdx, rdx
mul rbx

dec rcx

cmp rcx, 1 
jne .forLoop

mov qword[x_number], rax
push rax
mov r8, qword[x_number]
call itoa


mov rsi, newLine
mov rdx, newLine_L
mov rax, 1
mov rdi, 1
syscall



xor r8, r8
pop r8;mov the number into r8
pop rbx;restore rbx

mov qword[x_number], r8
mov r8, x_number;mov the adress into r8
add r8, 80
mov byte [r8], 0;put a zero after the number
sub r8, 80
xor rcx, rcx;clear out rcx for use

;add individual digits together
.forLoop2:
add cl, byte[r8]


add r8, 1;get ready for the next number

cmp byte[r8], 0;if this digit is equal not equal to zero then jump back to the top
jne .forLoop2
;print out the result stored in rcx
mov qword[x_number], rcx
mov r8, qword[x_number]
call itoa
;print out a new Line
mov rsi, newLine
mov rdx, newLine_L
mov rax, 1
mov rdi, 1
syscall

.done:

ret



« Last Edit: June 30, 2014, 04:07:07 AM by Anonymous »
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: traversing through a Register
« Reply #3 on: June 30, 2014, 05:54:02 AM »
You may need to refresh my memory on what your "itoa" does. It prints the ascii decimal representation of the number, right?... and leaves it in your buffer as a zero-terminated string? So...

2 - you enter the number
15 - you enter the power
32768 - you print the result
266 - you print the sum of the ascii characters
But wait! That's going to overflow cl, so:
10?

What does it do? If you expect it to print 26, you're going to have to subtract '0' from each character before you add it to cl...

I'm no less confused than before.

I think I can say with some confidence that your strings ought to be declared as "db" not "dq", but I doubt if that's your problem...

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: traversing through a Register
« Reply #4 on: June 30, 2014, 08:38:52 PM »
Well the result of my itoa is not stored in any register it just prints it the original integer is still in rax which is what I passed it in so I don't know why it is giving me 128 instead of 26
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: traversing through a Register
« Reply #5 on: July 02, 2014, 01:16:43 AM »
If it helps I am doing project euler problem 16
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: traversing through a Register
« Reply #6 on: July 02, 2014, 03:14:19 AM »
Oh.

What is the sum of the digits of the number 2^1000?

That's easy. 1. That's my answer and I'm sticking to it. They don't say decimal digits, although that's obviously the intent. Decimal would be an absolutely insane way to represent that number. Who would do such a thing? Oh, Euler...

First thing to do would be to calculate 2^1000, I guess - unless we just represent it as binary... Your routine to do 2^15 is not going to work for 2^1000! You'll need a "bignum" routine of some sort, I would think. But gotta start somewhere!

128, you say? That seems a strange result. I've gotta get that 64-bit machine running again so I can follow along better. Maybe soon...

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: traversing through a Register
« Reply #7 on: July 02, 2014, 08:45:06 PM »
I found another way to add the individual digits but I am still curious how you could grab the individual digits and add them directly and also I have been looking into Big numbers and How to handle them and they look extremely complex, One thing I know is that I have to find a way to store that big number into multiple registers like RBX:RCX and then how to manipulate them so I can add the individual digits here is a snippet of where I changed the code in the second forloop :
Code: [Select]
forLoop2:
div rcx;divide by 10
add r8, rdx;add the remainder to r8
xor rdx, rdx;clear out rdx
cmp rax, 0;if rax is not equal to zero then jump back to forLoop2
jne .forLoop2
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: traversing through a Register
« Reply #8 on: July 02, 2014, 09:13:14 PM »
I have commented out  my old code now to test if the number is too big but I have no Idea if I am going in the right direction with the "Bignum" I am trying to create, here it is
EDIT: As I have researched how to implement a Bignum I found this algorithm which I have tried to implement here but to no avail, it just prints out random numbers to me it looks like
Code: [Select]
PowerSum:

;power is passed in rcx
;number is passed in rax


mov r12, rax
xor r8, r8
xor r9, r9
xor r10, r10
mov r10, r10
xor r11, r11
xor rcx, rcx
;xor rsp, rsp
.forLoop:;calculates the n^x power
 
xor rdx, rdx;the remainder
mul r12;what we are multiplying by
add rax, r11
xor r11, r11;clear out the carry variable

dec rcx;counter
cmp rax, 10;if rax is not greater than or equal to 10 then jump to .next
jnge .next
add r11, 10
sub rax, r11

push rax;save the variable
push rcx;save the counter
printNum rax
pop rcx;restore the counter
pop rax;store the variable
.next:
cmp rcx, 1

jne .forLoop
ret
« Last Edit: July 08, 2014, 05:33:19 AM by Anonymous »
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: traversing through a Register
« Reply #9 on: July 08, 2014, 06:07:55 AM »
Is there anyone that could help me with implementing a Bignum in my code I have been looking all over and I have found nothing so far and I think I have tried everything or at least everything I can think of.
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: traversing through a Register
« Reply #10 on: July 08, 2014, 08:02:48 AM »
Well... no. This is a 32-bit version of what I think needs to be done. IT IS NOT CORRECT! I'm getting 1367 and the correct answer is apparently 1366. Obviously allowing 64 bits for the sum was overkill. (I tried it before looking up the answer) This can be simplified quite a lot. Finding my off-by-one error is left as an exercize for the student. :)

Best,
Frank

Code: [Select]
global _start

; purpose: attempt to calculate the sum
; of decimal digits in 2^1000 (euler problem 16)

; nasm -f elf32 prog.asm
; ld -o prog prog.o -m elf_i386

section .data

; 2^1000 = 125 bytes?
    number db 80h
    times 124 db 0
end_number:

section .bss
    sum_of_digits resd 2 ; enough?
    asciibuff resb 80h
; do we want to try to print this puppy?

section .text
_start:

    mov ebx, 10
    mov esi, number
    xor edx, edx
top:
    mov eax, [esi]
    div ebx
    mov [esi], eax
    add esi, 4
    cmp esi, end_number
    jb top

    add [sum_of_digits], edx
    adc dword [sum_of_digits + 4], 0
    mov esi, number
    xor edx, edx
check_zeros:
    cmp dword [esi], 0
    jne top
    add esi, 4
    cmp esi, end_number
    jb check_zeros

    mov eax, [sum_of_digits]
    mov edx, [sum_of_digits + 4]
    mov edi, asciibuff
    call u64toda
    mov ecx, asciibuff
    mov edx, 80 ; ?
    mov ebx, 1
    mov eax, 4
    int 80h

    mov eax, 1
    xor ebx, ebx
    int 80h

;--------------------------------------------------------------
; u64toda - converts (64 bit) integer in edx:eax
; to (comma delimited) decimal representation in
; asciiz ( & "$") terminated string in buffer pointed to by edi
;-----------------------------------------------------------------
u64toda:
                pusha
                mov ebx, edx     ; stash high dword
                mov esi,0Ah      ; prepare to divide by 10
                xor ecx, ecx     ; zero the digit count
                jmp highleft     ; check is high word 0 ?
highword:
                xchg eax,ebx    ; swap high & low words
                xor edx,edx     ; zero edx for the divide!
                div esi         ; divide high word by 10
                xchg eax,ebx    ; swap 'em back
                div esi         ; divide low word including remainder
                push edx        ; remainder is our digit - save it
                inc ecx         ; count digits
highleft:
                or ebx,ebx
                jnz highword
lowleft:
                xor edx,edx          ; zero high word
                div esi              ; divide low word by 10
                push edx             ; our digit
                inc ecx              ; count it
                or eax,eax           ; 0 yet ?
                jne lowleft
                cmp ecx, byte 4      ; commas needed ?
                jl write2buf         ; nope
                xor edx,edx            ; zero high word for divide
                mov eax,ecx            ; number of digits
                mov ebx,3
                div ebx
                mov esi,edx            ; remainder = number digits before comma
                test edx,edx
                jnz write2buf        ; no remainder?
                mov esi,3             ; we can write 3 digits, then.
write2buf:
                pop eax              ; get digit back - in right order
                add al,30H           ; convert to ascii character
                stosb                ; write it to our buffer
                dec esi               ; digits before comma needed
                jnz moredigits       ; no comma needed yet
                cmp ecx,2             ; we at the end?
                jl moredigits        ; don't need comma
                mov al,','           ; write a comma
                stosb
                mov esi,03h           ; we're good for another 3 digits
moredigits:
                loop write2buf       ; write more digits - cx of 'em
                mov al,00h           ; terminate buffer with zero
                stosb
popa
                ret
;-------------------------------------------------------------



Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: traversing through a Register
« Reply #11 on: July 08, 2014, 12:54:28 PM »
Apparently I wasn't representing 2^1000 correctly.
Code: [Select]
; 2^1000 = 125 bytes?
    number dd 100h
    times 31 dd 0
end_number:

Now it goes 1366.

Best,
Frank