x86 32位NASM中实现三位数加999并输出结果的问题
Fixing Carry Handling in Your 3-digit + 999 Assembly Program
Hey there! Let's work through that carry issue you're facing. The core problem is that your current code only handles the three digits of the input and addition, but doesn't account for the final carry that would create the fourth digit (the thousands place) when needed. Plus, we need to adjust how we store the results to make sure the output is in the correct order. Let's break down the fixes step by step:
What's Wrong with the Original Code
- Your loop processes the three digits correctly with
adcandaaa, but you're storing each result in the same index as the input digits. This leaves no space for the thousands-place carry. - When
aaasets the carry flag (CF) after the final (hundreds-place) addition, there's no code to capture that carry and turn it into the leading digit of your four-digit result.
Modified Code with Explanations
Here's the fixed version of your code, with comments explaining the key changes:
section .data numToAdd db "999",0x00 userPrompt db "Please enter a 3 digit number (000-999):", 0x0a, 0x00 len_userPrompt equ $-userPrompt section .bss userNum resb 4 ; user input: (3 digit num + \n) resultNum resb 4 ; Stores 4-digit result as ASCII string section .text global main main: ; Print prompt mov eax, 0x04 mov ebx, 0x01 mov ecx, userPrompt mov edx, len_userPrompt int 0x80 ; Read user input mov eax, 0x03 mov ebx, 0x00 mov ecx, userNum mov edx, 4 int 0x80 ; Initialize registers for addition loop mov edx, 2 ; Start with the ones place (index 2 of input strings) mov ecx, 3 ; Loop 3 times (ones, tens, hundreds) clc ; Clear carry flag before starting additions loop_here: mov al, [numToAdd + edx] ; Get the corresponding digit from 999 adc al, [userNum + edx] ; Add user's digit + carry from previous step aaa ; Adjust to BCD, sets CF if there's a carry pushf ; Save carry flag (add will modify flags) add al, 0x30 ; Convert BCD result back to ASCII popf ; Restore carry flag for next iteration mov [resultNum + edx + 1], al ; Store result in the correct position (ones→index3, tens→2, hundreds→1) dec edx loop loop_here ; Handle the final carry for the thousands place mov al, '0' adc al, 0x00 ; If CF is set, al becomes '0'+1='1'; stays '0' otherwise mov [resultNum], al ; Store thousands digit as first character in result ; Print the 4-digit result mov eax, 0x04 mov ebx, 0x01 mov ecx, resultNum mov edx, 0x04 int 0x80 ; Exit program mov eax, 0x01 int 0x80
Key Fixes Explained
- Result Storage Adjustment: We now store each digit result in
resultNum + edx + 1instead ofresultNum + edx. This shifts the ones/tens/hundreds results to the right by one position, leaving the first index (0) free for the thousands digit. - Carry Capture for Thousands Place: After the loop finishes, we check the carry flag with
adc al, 0x00. If there's a carry from the hundreds-place addition, this turns our initial '0' into '1', which we store as the leading digit of the result. - Correct ASCII Conversion: The
pushf/popfpair preserves the carry flag through the ASCII conversion step, ensuring the next iteration'sadcuses the correct carry value.
Testing this code with inputs like 100 will output 1099, and 999 will output 1998—exactly what you need!
内容的提问来源于stack exchange,提问作者Robert Tiger
相关产品推荐
相关产品推荐

