【问题标题】:Why Isn't this Assembly Program Accepting Input?为什么这个汇编程序不接受输入?
【发布时间】:2021-12-06 13:47:41
【问题描述】:

我正在编写一个程序,它将 0-4096 范围内的非负整数转换为 3 位十六进制数。问题是这个程序甚至不接受我的输入。我正在使用带有自定义宏的 SASM32。相反,它会溢出重复输出消息并使用 0 作为我们的输入。此外,由于返回提示的默认值为“Y”,因此它会一直持续到崩溃。

.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 

【问题讨论】:

  • “直到崩溃”。那么它在哪里崩溃呢?另外,当reprompt_flag 是下一行时,有条件地跳转到reprompt_flag 有什么意义?你在哪里跳回start
  • 跳转到“reprompt_flag”的重点是用户可能想要将另一个整数转换为十六进制。此外,如果用户输入 'N' 作为 'reprompt_char' 的输入,那么我们不会直接转到 'end start' 吗?
  • 想想条件分支的作用。它要么跳转以便在分支目标处继续执行,要么不跳转并在分支指令之后的指令处继续执行。

标签: assembly x86-64


【解决方案1】:
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 

这些操作的方向有很大的错误!
move user_input, input_store 中,我期望source -> destination,但在
move temp, user_input 中,它是destination <- source。 不能同时是...

假设destination <- source会发生这种情况:

  1. 因为 input_store 为 0,所以 move user_input, input_store 行会破坏输入并将其设为零。
  2. 商和余数的计算结果为零。
  3. quotient 加载 user_input 后,它将为零(再次)。
  4. 最后compare user_input, 0 bez return1 会一直跳转到return1


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

reprompt_flag:
  br start

像上面这样的代码构成了一个无限循环。如果答案是“Y”,您分支到前往开始的指令,如果答案不是“Y”(这与已输入不同) 'N') 你通过开始的指令。无论哪种方式,您都可以重复该程序。

试试下面的。这样,回答“Y”的用户将重新运行程序,而任何其他回答都将通过退出。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    相关资源
    最近更新 更多