Home > Mobile >  Why Isn't this Assembly Program Accepting Input?
Why Isn't this Assembly Program Accepting Input?

Time:10-20

I am writing a program that converts nonneg integers ranging from 0-4096 to a 3 digit hexadecimal number. Problem is that this program isn't even accepting my input. I am using SASM32 with custom macros. Instead, it overflows repeating the output messages and using 0 as our input. Also since the default for the return prompt is 'Y' it continues until a crash.

.486
include C:\Program Files (x86)\SASM\include\sasmacros.inc


.data 
;Messages 
inputmsg db 'Input decimal integer to convert:',0
outputmsg db 'in hexadecimal is:',0
reprompt_msg db 'Convert another integer? (Y/N):',0 
reprompt_char db 'N'

;Variables 
input_store dd 0
user_input dd 0

temp dd 0
remainder_store dd 0 


quotient dd 0 
remainder dd 0 
temp_remainder dd 0 

hexnumber dd 0 DUP(100)
output dd 1, 2, 3

;main loop control is positions and user_input 
;record each hex position as a character or digit(either one will be 0 or digit)
positions dd 0 
pos1 db '0'
pos2 db ' '
pos3 db ' '


.code

;take number and divide it by 16 and at the remainder of it to the output
;divide -> check remainder (if n > 9) -> add hex number loop -> divide loop
; store the quotient for the next iteration of dividing
;  divide until our remainder or the result of our mod is == 0 

;for reprompt just compare if N - N == 0 is true

;if input is less than 15 then just return it 

                   

start:
    get_i user_input
    move user_input, input_store ; store our input before it is lost 
    ;might delete
    ;might delete
    br divide

divide:

    ;divide by 16
    move temp, user_input ; setting temp to the current input 
    idivi temp, 16
    move quotient, temp ;quotient = temp 
    move temp, user_input ;temp = input
    irem temp, 16 ; takes remainder of temp and saves it as temp
    move remainder, temp ;remainder = temp
    ;set our input = quotient 
    move user_input, quotient ; storing our input for next loop as quotient 
    br store_result
    
store_result:

    compare user_input, 0 ;if our user_input is 0 (which becomes the quotient of the previous calculation), then finish
    bez return1           ; problem is that we would also hit this case if our input is 0
    ;check for 0
    compare remainder, 10
    bgez convert_to_upper_hex
    
    ;otherwise just store our remainder and loop again
    ;48 - remainder = character representation of remainder ASCII
    iadd positions, 1 ; increment positions 
    iadd remainder, 48 ; create ascii value 
    br figure_what_to_store


    ;converts digits 10-15 
convert_to_upper_hex:
    iadd positions, 1 ;have to increment still in this loop
    iadd remainder, 41 ;make it A-F using ASCII starting at 'A'
    br figure_what_to_store

figure_what_to_store:
    compare 1, positions
    bez store_pos_one

    compare 2, positions
    bez store_pos_two

    compare 3, positions
    bez store_pos_three


store_pos_one:
    move pos1, remainder ;move remainder into pos1
    br divide 

store_pos_two:
    move pos2, remainder 
    br divide 

store_pos_three:
    move pos3, remainder 
    br return1
    ;end loop here 

return1: 
     put_i input_store
     put_str outputmsg
     ;update displaying integer
     compare positions, 1
     bez return_single
     compare positions, 2 
     bez return_double
     
     ;if we aren't displaying 1 or 2 digits, then we are displaying 3
     put_ch pos3
     put_ch pos2
     put_ch pos1
     ;check if more positions, if so bnz return
     br reprompt

return_single:
    put_ch pos1
    br reprompt 
    
return_double:
    put_ch pos2
    put_ch pos1
    br reprompt    
     
reprompt:
     put_str reprompt_msg 
     get_ch reprompt_char
     compare reprompt_char, 'Y' ;if N was entered 
     bez reprompt_flag
     
reprompt_flag:
    ;also clear output 
    br start
    
    exit
end start 

CodePudding user response:

move user_input, input_store ; store our input before it is lost 
;divide by 16
move temp, user_input ; setting temp to the current input 

There's something very wrong here about the direction of these operations!
In move user_input, input_store, I'd expect source -> destination, but in
move temp, user_input it's rather destination <- source. It can't be both at the same time...

Assuming destination <- source this is what happens:

  1. Because input_store holds 0, the line move user_input, input_store destroys the input and makes it zero.
  2. The calculations for both quotient and remainder will yield zero.
  3. After loading the user_input from quotient it will be zero (again).
  4. Finally compare user_input, 0 bez return1 will always jump to return1.


  compare reprompt_char, 'Y' ;if N was entered 
  bez reprompt_flag

reprompt_flag:
  br start

Code like the above constitutes an endless loop. If the answer was 'Y', you branch to the instruction that goes to start, and if the answer is not 'Y' (which is not the same as having entered 'N') you fall through in the instruction that goes to start. Either way you repeat the program.

Try the following. This way the user answering 'Y' will rerun the program, while any other answer will fall through in the exit.

reprompt:
     put_str reprompt_msg 
     get_ch reprompt_char
     compare reprompt_char, 'Y'
     bez start
     
    exit
end start
  • Related