You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86汇编中如何支持大整数输入?MyReadInt处理4000000007失败

修改x86汇编MyReadInt以支持大整数输入

我编写了一个x86汇编程序,功能是接收非负整数并判断其是否为素数,但输入4000000007时程序返回TryAgain错误。排查后发现问题出在MyReadInt过程——它仅能处理32位范围内的无符号整数,无法支持更大的数值输入,现需要修改该过程以支持更大的整数。

原代码片段如下:

INCLUDE Irvine32.inc

.DATA
startTime DWORD ?
enter1 BYTE "Enter a non-negative integer (0 to exit): ",0
tryAgain BYTE "That input is not allowed. Try again.",0
prime BYTE " is a prime number.",0
notPrime BYTE " is not a prime number; it is divisible by: ",0
exitMessage BYTE "Goodbye",0
time BYTE "Procedure runtime in milliseconds: ",0
LMAX_DIGITS = 80
Linputarea BYTE LMAX_DIGITS dup(0),0
overflow_msgL BYTE " <32-bit integer overflow>",0
invalid_msgL BYTE " ",0 
neg_msg BYTE " ",0


.code
main PROC
beginning: mov edx, OFFSET enter1 
           call WriteString     ; writes null-terminated string to standard output
           call MyReadInt       ; input stored in eax 
           cmp eax, 0           ; compares eax to 0
           jge noError          ; continue if input >= 0
           mov edx, OFFSET tryAgain ; if number is negative, write error message
           call WriteString     ; writes null-terminated string to standard output
           jmp beginning        ; loop beginning 
        
noError:
; 此处省略素数判断逻辑(原代码未完整给出)
           jmp beginning

main ENDP
                                    ; end of procedure
;______________________________________________________________________________
; MyReadInt PROC 
; Modified from Irvine32.asm by _________
; Reads a 32-bit unsigned decimal integer from standard
; input, stopping when the Enter key is pressed.
; All valid digits occurring before a non-numeric character
; are converted to the integer value. Leading spaces are
; ignored, and an optional leading + sign is permitted.
; Receives: nothing
; Returns: If CF=0, the integer is valid, and EAX = binary value.
; If CF=1, the integer is invalid and EAX = 0.
;______________________________________________________________________________
 MyReadInt PROC uses ebx ecx edx esi

    ; Input a string of digits using ReadString.
    mov edx,offset Linputarea
    mov esi,edx                                         ; save offset in ESI
    mov ecx,LMAX_DIGITS
    call ReadString
    mov ecx,eax                                         ; save length in ECX
    cmp ecx,0                                           ; greater than zero?
    jne L1                                              ; yes: continue
    mov eax,0                                           ; no: set return value
    jmp L9                                              ; and exit

; Skip over any leading spaces.
L1: mov al,[esi]                                    ; get a character from buffer
    cmp al,' '                                      ; space character found?
    jne L2                                          ; no: check for a sign
    inc esi                                         ; yes: point to next char
    loop L1
    jcxz L8                                         ; quit if all spaces

; Check for a leading sign.
L2: cmp al,'-'                                      ; minus sign found?
    jne L3                                          ; no: look for plus sign
    mov edx, offset neg_msg                         ; tell user negative numbers not allowed
    jmp L8

L3: cmp al,'+'                                      ; plus sign found?
    jne L4                                          ; no: must be a digit
    inc esi                                         ; yes: skip over the sign
    dec ecx                                         ; subtract from counter

; Test the first digit, and exit if it is nonnumeric.
L3A:mov al,[esi]                                    ; get first character
    call IsDigit                                    ; is it a digit?
    jnz L7A                                         ; no: show error message

; Start to convert the number.
L4: mov eax,0                                   ; clear accumulator
    mov edx,0                                   ; 新增:清空64位累加器的高32位
    mov ebx,10                                  ; EBX is the multiplier

; Repeat loop for each digit.
L5: mov cl,[esi]                                    ; 改用CL存储当前字符,避免占用EDX
    cmp cl,'0'                                      ; character < '0'?
    jb L10
    cmp cl,'9'                                      ; character > '9'?
    ja L10
    and ecx,0Fh                                     ; convert to binary digit (存于CL)

    ; 先检查当前64位值乘以10后是否会溢出
    ; 64位最大值0xFFFFFFFFFFFFFFFF,除以10得0x1999999999999999
    cmp edx, 0x19999999
    ja L6                                           ; EDX > 0x19999999,乘以10必溢出
    jb MultiplyTen                                   ; EDX < 0x19999999,可安全乘10
    ; EDX == 0x19999999,检查EAX是否超过0x99999999
    cmp eax, 0x99999999
    ja L6                                           ; EAX > 0x99999999,乘10后溢出

MultiplyTen:
    ; 计算EDX:EAX = EDX:EAX * 10
    push ecx                                        ; 保存当前数字
    mov ecx, ebx                                    ; ECX = 10
    mul ecx                                         ; EDX:EAX = EAX * 10
    pop ecx                                         ; 恢复数字

    ; 加上当前数字
    add eax, ecx
    adc edx, 0                                      ; 处理进位到EDX

    inc esi                                         ; point to next digit
    jmp L5                                          ; get next digit

; Carry out of 64 bits has occured, choose "integer overflow" messsage.
L6: mov edx,OFFSET overflow_msgL
    ; 可将overflow_msgL修改为" <64-bit integer overflow>"以明确提示
    jmp L8

; Choose "invalid integer" message.
L7A:mov edx,OFFSET invalid_msgL

; Display the error message pointed to by EDX.
L8: call WriteString
    call Crlf
    mov eax,0                                       ; set return value to zero
    mov edx,0                                       ; 清空高32位

L9: stc                                             ; set Carry flag to indicate error
    ret

L10: clc                                            ; clear Carry flag to indicate success
     ret
MyReadInt ENDP
END main

修改说明

  1. 扩展为64位存储:将原32位累加器EAX扩展为EDX:EAX组合的64位累加器,最大可支持到18446744073709551615(2^64-1)的无符号整数,完全覆盖4000000007这类数值。
  2. 溢出判断优化:在乘以10前先检查当前64位值是否超过64位最大值除以10的阈值,提前拦截溢出情况,避免计算后的数据损坏。
  3. 寄存器调整:改用CL存储当前读取的字符,避免占用作为累加器高32位的EDX。
  4. 进位处理:在加上当前数字后,使用adc edx,0处理可能产生的进位到高32位EDX,保证64位数值的正确性。

内容的提问来源于stack exchange,提问作者Caroline Warner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:18:09