0

(Preliminary information: As a newbie I managed to do a one digit calculator finally, but to do a multi-digits calculator I had to get some 'inspiration' from the internet as it is seen in the code.) The problem is when I hardcoded the input numbers calculator works perfectly ok. But when I try to get inputs from the users results are totally chaotic. I am working on this issue to solve it for almost 3 days but no solution. If anyone can help me I d be really appreciated. Thank you everyone

section .data


msg2        db      'Enter the first number: ',0xA,0xD
lmsg2       equ     $- msg2

msg3        db      'Enter the second number: ',0xA,0xD
lmsg3       equ     $- msg3

msg9        db      10,'Result= ',0
lmsg9       equ     $- msg9





section .bss
; Spaces reserved for storing the values provided by the user.  
num1       resd    4   ;;;;;;;;;;;UPDATED
num2       resd    4   ;;;;;;;;;;;UPDATED
result     resd    8   ;;;;;;;;;;;UPDATED
result_len  resd   1   ;;;;;;;;;;;UPDATED


section .text
global _start
_start:



; Print on screen the message 2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, lmsg2
int 80h

; We get num1 value.
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 4
int 80h

; Print on screen the message 3
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, lmsg3
int 80h

; We get num2 value.
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 4
int 80h




mov eax, 12 ;;;;;;;[num1]  WHEN BEING PUT A NUMBER DIRECTLY IT WORKS
mov ebx, 55 ;;;;;;;;[num2] UPDATED- WHEN BEING PUT A NUMBER DIRECTLY IT WORKS

; Convert from ascii to decimal
  sub eax, '0'  ;;;;;;;;;;; UPDATED- COMMENTED OUT 
  sub ebx, '0'  ;;;;;;;;;;; UPDATED- COMMENTED OUT 

; Add
add eax, ebx

; Conversion from decimal to ascii
add eax, '0'   ;;;;;;;;;;; UPDATED- COMMENTED OUT 



; THIS IS THE AREA PROBLEMS HAPPEN
mov edi, result                ;  argument: Address of the target string 
call int2str                ; Get the digits of EAX and store it as ASCII
sub edi, result                ; length of the string
mov [result_len], edi



; Output "The sum is: "
mov eax, 4
mov ebx, 1
mov ecx, msg9
mov edx, lmsg9
int 0x80




; Output sum
mov eax, 4
mov ebx, 1
mov ecx, result
mov edx, [result_len]     ;;;;;;;;;;;UPDATED
int 0x80


; Exit code
mov eax, 1
mov ebx, 0
int 0x80






;LOOPS FOR DOING THE MULTI DIGITS OPERATION
int2str:    ; Converts an  integer in EAX to a string pointed to by EDI
xor ecx, ecx                  
mov ebx, 10
.LL1:                   ; First loop: Save the remainders
xor edx, edx            ; Clear EDX for div
div ebx                 ; EDX:EAX/EBX -> EAX Remainder EDX
push dx                 ; Save remainder
inc ecx                 ; Increment push counter
test eax, eax           ; Anything left to divide? 
jnz .LL1                ; if Yes: loop once more.. jump if not zero

.LL2:                   ; Second loop: Retrieve the remainders
pop dx                  ; In DL is the value
or dl, '0'              ; To ASCII
mov [edi], dl           ; Save it to the string  (
inc edi                 ; Increment the pointer to the string
loop .LL2               ; Loop ECX times

mov byte [edi], 0       ; Termination character
ret                     ; RET: EDI points to the terminating NULL
mears
  • 359
  • 4
  • 13
  • 1
    `sub eax, '0'` conversion from ASCII to integer only works for one-digit numbers. Look at the values in registers with your debugger while you single-step. Also, `resb 2` only reserves 2 bytes, but you're loading a dword (4 bytes), so EAX has `(num2 << 16) | num1`. – Peter Cordes Dec 21 '18 at 23:09
  • Sir, thank you very much for your time. But even when I try with single digits, "THIS IS THE AREA PROBLEMS HAPPEN" part causes the error as I could see. Because when I comment out that part and use normal "mov [result], eax" instead code works for single digit. I am sorry, I don't know much and can't understand easily the logic – mears Dec 22 '18 at 10:44
  • 1
    What error? you didn't show what your code actually prints, so this isn't a [mcve]. Anyway, it's probably a result of loading 4 bytes from `num1`, getting both num1 and num2 into EAX like I commented before. *Use a debugger*. For single-digit inputs, try using `movzx eax, byte [num1]` / `movzx ebx, byte [num2]`. Your int->string conversion looks correct. I might have missed a bug in there somewhere, and it is clunky, but there are obvious problems elsewhere. – Peter Cordes Dec 22 '18 at 16:19
  • sir thank you for your response again. As you pointed i made the changes and the end result looks like in the updated code. I tried but couldn't handle the debug part but when I try the program like this (with getting input from user) it gives +5216 from the real result. – mears Dec 24 '18 at 14:30
  • 1
    But WHEN i put normal numbers as mov eax, 12 , mov ebx, 55 instead of mov eax,[num1], mov ebx,[num2] code works perfectly again. So it s for sure the problem is about getting the inputs from the user.. Thanks for the suggestions of anyone – mears Dec 24 '18 at 14:48
  • 1
    `resd 4` reserves 4 dwords of space, 16 bytes. You probably want `resd 1` to reserve one dword. – Peter Cordes Dec 24 '18 at 18:23
  • thanks, I tried changing resb resd values with different combinations(including resd 1 ) but all in all still +5216 deviation from real calculation. Pretty strange :s – mears Dec 25 '18 at 08:37
  • 1
    Reserving more space than you need isn't a bug, it's just a missed optimization. Obviously you're still converting from a string to an integer incorrectly, so the linked duplicate still applies; use its code or use a debugger. Probably you're failing to subtract `'0'` from *each* ASCII decimal digit as you loop over them, and/or not adding them up correctly. `0x30 * 111` is decimal 5328, so yeah your error is pretty close to what you'd expect for the place-values of an extra `0x30` (ASCII `'0'`) in each digit of a 3-digit decimal number, – Peter Cordes Dec 25 '18 at 09:26

0 Answers0