为什么基于SASM32的非负整数转三位十六进制汇编程序无法接收输入?
Alright, let's work through the issues in your SASM32 assembly program one by one. I'll break down what's going wrong and show you a fixed version of the code with explanations.
Key Issues Identified
1. No Input Prompt (Why You Can't "Enter" Input)
Your program jumps straight to get_i user_input without first displaying the inputmsg prompt. Users have no idea they need to type a number, so they might not input anything—leading get_i to default to 0.
2. Broken Reprompt Loop (Infinite Cycle Until Crash)
Your reprompt logic is backwards:
- You check if the input is
'Y'and jump toreprompt_flag, but regardless of the input, the code then runsbr startto loop again. Even if the user types'N', it never hits theexitinstruction.
3. Result Processing Order (Losing Remainders for Small Numbers)
In store_result, you first check if the quotient is 0 and jump out—this means for numbers less than 16 (like 5), you never process the remainder before exiting the loop. The program outputs the initial pos1 value (0) instead of the correct digit.
4. Signed Math for Unsigned Values
You’re using idivi and irem (signed division/remainder) for non-negative integers. This can cause unexpected overflow or calculation errors. Switch to unsigned versions divi and rem instead.
5. Incorrect Hex Position Initialization
Your pos2 and pos3 start as spaces, but three-digit hex should use leading zeros (e.g., input 5 should show 005, not 0). Also, input 0 wasn’t being handled to set all positions to 0.
Fixed Code
.486 include C:\Program Files (x86)\SASM\include\sasmacros.inc .data ; 消息定义 inputmsg db 'Input decimal integer (0-4096) to convert:',0 outputmsg db ' in hexadecimal is: ',0 reprompt_msg db 'Convert another integer? (Y/N):',0 ; 变量定义 input_store dd 0 user_input dd 0 quotient dd 0 remainder dd 0 positions dd 0 ; 初始化所有位置为'0'(补前导0) pos1 db '0' pos2 db '0' pos3 db '0' .code start: ; 先显示输入提示,再获取输入 put_str inputmsg get_i user_input move input_store, user_input ; 保存原始输入值 ; 处理输入0的特殊情况 compare user_input, 0 bez display_result divide_loop: ; 无符号除法和取余(因为处理非负整数) move eax, user_input divi eax, 16 move quotient, eax ; 商 = user_input / 16 move eax, user_input rem eax, 16 move remainder, eax ; 余数 = user_input % 16 ; 更新user_input为商,用于下一次循环 move user_input, quotient ; 处理余数,转换为ASCII字符 iadd positions, 1 compare remainder, 10 bgez convert_to_hex_char ; 余数>=10,转A-F ; 余数<10,转数字字符 iadd remainder, 48 br store_hex_digit convert_to_hex_char: iadd remainder, 55 ; 'A'是65,65-10=55,所以余数+55得到A-F的ASCII值 store_hex_digit: ; 根据位置存储字符 compare positions, 1 bez store_pos1 compare positions, 2 bez store_pos2 compare positions, 3 bez store_pos3 store_pos1: move pos1, remainder ; 如果商不为0,继续循环 compare user_input, 0 bnz divide_loop br display_result store_pos2: move pos2, remainder compare user_input, 0 bnz divide_loop br display_result store_pos3: move pos3, remainder br display_result ; 三位已满,直接显示 display_result: put_i input_store put_str outputmsg ; 按高位到低位输出三位十六进制 put_ch pos3 put_ch pos2 put_ch pos1 put_ch 10 ; 换行,提升可读性 reprompt: put_str reprompt_msg get_ch reprompt_char ; 判断输入:如果是'Y'或'y',重新开始;否则退出 compare reprompt_char, 'Y' bez start compare reprompt_char, 'y' bez start ; 不是Y/y,退出程序 exit end start
What Changed & Why
- Added input prompt: Now users see
Input decimal integer (0-4096) to convert:before being asked to type. - Fixed reprompt logic: Checks for
'Y'/'y'to loop, otherwise exits cleanly. - Reordered result processing: Processes the remainder first, then checks if the quotient is 0 to continue looping—no more lost digits for small numbers.
- Switched to unsigned math: Uses
diviandreminstead of signed versions to avoid overflow with non-negative values. - Initialized positions to '0': Ensures leading zeros for numbers with fewer than three hex digits (e.g., 5 becomes
005, 16 becomes010). - Added input 0 handling: Directly jumps to display if input is 0, showing
000. - Added newline: Makes output easier to read between conversions.
内容的提问来源于stack exchange,提问作者Zachery Uporsky

