1

I'm super new to assembly, and I've spent literally hours trying to figure this out. The program I'm making is supposed to take two numbers from zero to nine, then multiply them and show the correct answer (ex: 9 times 3 is 27). I need to have the 2 numbers be input from the user with the notation of "space number space number" (an example could be " 5 3"). I tried making the code without input (hardcode the numbers) and that works, but when I try to make the numbers come from input, the result is wrong. The program is supposed to take two numbers from zero to nine, then multiply them. I really can't figure out what's wrong...Any help at all would be very much appreciated.

When I enter: " 5 3" it outputs "? 4" (it should be 15)

When I enter: " 9 3" it still outputs "? 4" (it should be 27)

When I enter: "5 3" it outputs "?6"

When I enter: "9 3" it outputs "??4"

When I check var1 and var2 (by making it print them after them being read), the numbers are correct. As in, if " 5 3" is entered var1 does print 5 and var2 does print 3. Even if the spaces are changed, var1 and var2 print the correct numbers (so if I enter "5 3" var1 is still 5, and var2 is still 3).

My professor just explained what to do to get input, but I'm not 100% sure how it works. I find it odd that the output is different depending on where the spaces are, as var1 and var2 should both be accepting 2 bytes.

My code that's incorrect:

;this program multiplies two numbers input by the user, being able to solve with two digits
;the notation for the input should be space number space number (ex:" 9 3")


section .data

section .bss

    var1 resb 2
    var2 resb 2
    result resb 2
    tensdigit resb 2
    onesdigit resb 2
    
section .text
    global _start

_start:
    ;reads & saves user input for var1
    mov eax, 3
    mov ebx, 0
    mov ecx, var1
    mov edx, 2  ;2 bytes of info 
    int 80h
    


    ;reads & saves user input for var2
    mov eax, 3
    mov ebx, 0
    mov ecx, var2
    mov edx, 2  ;2 bytes of info 
    int 80h


    mov al, [var1]
   ; sub al, '0' ;not sure if this is needed or not

    mov bl, [var2]
   ; sub bl, '0'

   ;multiply bl by al
    mul bl
   ; sub ax, '0'
    mov [result], ax
   

                         
    ;divide by ten
    mov ax, 0 ;set the register to 0! Very important to avoid errors
    mov ax, [result]
    mov bx, 10
    div bx ;divide by ten
    
    mov [tensdigit], al ;this should have 1 if using 12 (2 if 24, etc)
    
    mov ax, [result]
    sub ax, 10
    mov [result], ax ;move new number into result
    
    mov al, [result]
    mov bl, 10
    div bl
    ;find the remainder
    mov [onesdigit], ah
    
    add [tensdigit], word '0' ;add 0 to ensure it's considered a number
    add [result], word '0'
    add [onesdigit], word '0'

    ;print tensdigit
    mov eax, 4
    mov ebx, 1
    mov ecx, tensdigit
    mov edx, 2
    int 80h 
    
    ;print onesdigit
    mov eax, 4
    mov ebx, 1
    mov ecx, onesdigit
    mov edx, 2
    int 80h 


    ;system exit
    mov eax,1           
    mov ebx,0   
    int 80h;

This is my code when the numbers are hardcoded (this one multiplies the numbers correctly):

;this program adds two numbers, being able to solve with two digits

section .data

section .bss
    var1 resb 2
    var2 resb 2
    result resb 2
    tensdigit resb 2
    onesdigit resb 2
    
section .text
    global _start

_start:


    ;setup the variables
    mov [var1], word 9
    mov [var2], word 3
    mov al, [var1]
    mov bl, [var2]
    mul bl
    mov [result], ax

    
                         
    ;divide by ten
    mov ax, 0 ;set the register to 0! Very important to avoid errors
    mov ax, [result]
    mov bx, 10
    div bx ;divide by ten
    
    mov [tensdigit], al ;this should have 1 if using 12 (2 if 24, etc)
    
    mov ax, [result]
    sub ax, 10
    mov [result], ax ;move new number into result
    
    mov al, [result]
    mov bl, 10
    div bl
    ;find the remainder
    mov [onesdigit], ah
    
    add [tensdigit], word '0' ;add 0 to ensure it's considered a number
    add [result], word '0'
    add [onesdigit], word '0'

    ;print tensdigit
    mov eax, 4
    mov ebx, 1
    mov ecx, tensdigit
    mov edx, 2
    int 80h 
    
    ;print onesdigit
    mov eax, 4
    mov ebx, 1
    mov ecx, onesdigit
    mov edx, 2
    int 80h 


    mov eax,1           
    mov ebx,0   
    int 80h;
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Angela M
  • 11
  • 2
  • `sub al, '0'` is needed for single-digit ASCII -> integer input. See [Why is my assembly output in letter position? (1+1=b)](https://stackoverflow.com/q/62828237). For multi-digit output, yes you need to divide by 10, but one `div` already gives you both quotient (10s digit) and remainder (1s digit): you don't need to redo `div` unless you want to handle more than 2 digits. – Peter Cordes Sep 21 '20 at 01:30
  • 2
    I think you're being inconsistent with your operand size and where the outputs go: `mov ax, 0` makes no sense before you overwrite AX with a load, and you forgot to zero DX. See [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) for an int->string function that handles multiple digits; you can simplify it to not loop if you want. – Peter Cordes Sep 21 '20 at 01:32
  • 1
    Single-step your code with a debugger and watch register values; that should help you see when your numbers start going wrong. – Peter Cordes Sep 21 '20 at 01:46

0 Answers0