Author Topic: cant understand what the error is  (Read 3051 times)

Offline ABHISHEK VIJAYAN

  • Jr. Member
  • *
  • Posts: 2
cant understand what the error is
« on: January 12, 2013, 11:24:47 AM »
I'm trying to write a code for finding sum of two 2-digit numbers without push or pop.
i use "nasm -f elf sum2.asm","ld -s -o sum2 sum2.o","./sum2" for executing
i dont get proper output.cant understand why.pls help me out
Code: [Select]
section .text

global _start:
       _start:

mov eax,4
        mov ebx,1
        mov ecx,prompt
        mov edx,pl
int 80h

mov eax,4
        mov ebx,1
        mov ecx,prompt1
        mov edx,p1l
int 80h

mov eax,3
mov ebx,0
mov ecx,dig11
mov edx,1
int 80h

mov eax,3
mov ebx,0
mov ecx,dig10
mov edx,2
int 80h

mov eax,4
        mov ebx,1
        mov ecx,prompt2
        mov edx,p2l
int 80h

mov eax,3
mov ebx,0
mov ecx,dig21
mov edx,1
int 80h

mov eax,3
mov ebx,0
mov ecx,dig20
mov edx,2
int 80h

sub byte[dig11],30h
sub byte[dig10],30h
sub byte[dig21],30h
sub byte[dig20],30h

        mov al,[dig11]
        mov bl,10
mul bl
add al,[dig10]
        mov [num1],al

        mov al,[dig21]
        mov bl,10
mul bl
add al,[dig20]
        mov [num2],al

        mov al,0
        add al,byte[num1]
        add al,byte[num2]
        mov byte[sum],al

mov bl,10
div bl
mov [digs0],ah
        mov [sumpart],al
        movzx ax,[sumpart]
mov bl,10
div bl     
mov [digs2],al
mov [digs1],ah

add byte[digs2],30h
add byte[digs1],30h
add byte[digs0],30h

mov eax,4
        mov ebx,1
        mov ecx,msgs
        mov edx,msgl
int 80h

mov eax,4
mov ebx,1
mov ecx,digs2
mov edx,1
int 80h

mov eax,4
mov ebx,1
mov ecx,digs1
mov edx,1
int 80h

mov eax,4
mov ebx,1
mov ecx,digs0
mov edx,1
int 80h

        mov eax,1
        mov ebx,0
        int 80h



section .data

prompt:db "SUM OF TWO 2-DIGIT NUMBERS",10
pl:equ $-prompt
prompt1:db "ENTER FIRST 2-DIGIT NUMBER",10
p1l:equ $-prompt1
prompt2:db "ENTER SECOND 2-DIGIT NUMBER",10
p2l:equ $-prompt2
msgs:db "SUM = "
msgl:equ $-msgs


section .bss

num1:resb 1
num2:resb 1
        dig10:resb 1
dig11:resb 1
dig20:resb 1
dig21:resb 1
sum:resb 1
sumpart:resb 1
digs2:resb 1
digs1:resb 1
digs0:resb 1

   
« Last Edit: January 12, 2013, 11:42:23 AM by ABHISHEK VIJAYAN »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2384
  • Country: us
Re: cant understand what the error is
« Reply #1 on: January 12, 2013, 03:03:37 PM »
Well... this turns out to be an interesting puzzle! I think the issue is with the way sys_read from stdin works. It doesn't return until "enter" is pressed. Only the number of bytes/characters specified in edx go into our buffer. Anything else typed - including the linefeed produced by "enter" - stays in the system's input buffer. On the next sys_read, this "extra" is available to be read. This time you've got edx = 2. I would "expect" this to put the second digit typed into the intended buffer, and the linefeed into the next variable. Not really what we "intended", but it shouldn't be a "killer" because we overwrite that with the next sys_read... or so I would "expect"...

The issue I'm having is with running it in a debugger. At the first prompt, I type "12(enter)". The "1" should go into the first buffer. So far, so good. But the "extra" - the "2" and the linefeed - are showing up in the "debug" prompt, causing my debugger to complain about an unknown command, and making that input unavailable for the next sys_read! I tried getting around this problem by setting a breakpoint after the sys_read's are all done. This "appears" to work, but after subtracting '0' (30h) from each buffer, I'm getting an unexpected value from "mov al, [dig11]". I have not yet figured out why. May require more coffee! :)

The way I would have approached this would have been to reserve a 3-byte buffer for each 2-digit number, and done a single sys_read with edx = 3 for each number we want - ignoring the linefeed in the third byte. (this ASSumes that the pesky user does as instructed!) I would "expect" the way you're doing it to work out pretty much the same way, but something "unexpected" seems to be happening. "Stuff happens" as we say on a family-oriented forum. :)

I'll study this more. More coffee, maybe even some food may help. Stay tuned.

Best,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2384
  • Country: us
Re: cant understand what the error is
« Reply #2 on: January 12, 2013, 03:25:31 PM »
Okay, I have gotten somewhat better results by simply rearranging your variables slightly...
Code: [Select]
num1:resb 1
num2:resb 1

;        dig10:resb 1
dig11:resb 1
        dig10:resb 1

; dig20:resb 1
dig21:resb 1
dig20:resb 1

sum:resb 1
sumpart:resb 1
digs2:resb 1
digs1:resb 1
digs0:resb 1

I've only tested this slightly, and don't consider it ideal. The way you had it, the second sys_read was overwriting the buffer from the first sys_read, rather than the "next" variable as I was "expecting". I don't think this is a great solution, but maybe it'll help you a little...

Later,
Frank

   

Offline ABHISHEK VIJAYAN

  • Jr. Member
  • *
  • Posts: 2
Re: cant understand what the error is
« Reply #3 on: January 12, 2013, 04:31:13 PM »
thanx Frank Kotler...  :)
i tried rearranging the declarations like u said.. and it works..still dont understand why...
i tried giving other names to these labels..and it works...all without a reason...  :-\

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2384
  • Country: us
Re: cant understand what the error is
« Reply #4 on: January 12, 2013, 07:16:33 PM »
Well, there's a reason. There's nothing "random" or "magic" going on - although it certainly seems that way sometimes! I think it's a question of what gets overwritten with what, and when. The names shouldn't matter, but the order may...

I would consider it a "bug" to do a sys-read with edx = 2 and only provide a one-byte buffer. This will "clobber" the next byte. If we then re-write the "clobbered" byte with the intended value, it won't really hurt... but it's still a "bug". You could fix this by making the buffers you're reading into with edx = 2 "resb 2" instead of "resb 1" - just ignore the extra byte (which should be a linefeed).

I mentioned that sys_read (from stdin - from a disk file is different) doesn't return until we hit "enter". The linefeed (10 decimal or 0Ah) either goes into our buffer (if edx is big enough), or stays in the OS's input buffer to be read "next time". Your code "counts on" this. Might be "better" if it didn't, but if it works, it works.

Best,
Frank