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

x86 AT&T汇编重复减法除法程序异常问题求助

x86 AT&T汇编大整数重复减法除法程序异常修复

需求与问题

程序需求:从STDIN读取32字节作为被除数,再读取32字节作为除数,采用重复减法除法算法实现大整数除法,最终通过STDOUT输出32字节的商和32字节的余数。

程序异常表现:有时可正常运行,无需修改代码仅重新汇编链接后,会出现无法完整读取输入数据的情况,后续输出结果错误。

原代码

EXIT_NR  = 1
READ_NR  = 3
WRITE_NR = 4

STDOUT = 1
STDIN = 0

EXIT_CODE_SUCCESS = 0

.data
dividend: .space 32
divisior: .space 32
quotient: .space 32
rest: .space 32

.text
.global _start
_start:
read:
movl $READ_NR, %eax
movl $STDIN, %ebx
movl $dividend,%ecx
movl $64, %edx
int $0x80

clc
cmp $0,%eax
jle end

movl $31,%esi
div_loop:
    clc
    cmp $0,%esi 
    je done
    movb dividend(%esi), %al 
    movb divisior(%esi),%bl
    xor %dl,%dl 
    sub_loop:
        sbbb %bl,%al
        jc odtw
        inc %dl
        jmp sub_loop
    odtw:
        movb %dl,result(%esi)
        addb %bl,%al
        movb %al,rest(%esi)
        dec %esi
        jmp div_loop
done:

movl $WRITE_NR,%eax
movl $STDOUT,%ebx
movl $result, %ecx
movl $64, %edx
int $0x80

jmp read

end:
movl $EXIT_NR, %eax
movl $EXIT_CODE_SUCCESS, %ebx
int $0x80

示例输入与错误输出

输入(64字节十六进制):

00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 0b  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 02  |................|

错误输出(64字节十六进制,商+余数):

00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 05  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 01  |................|

(注:此示例输出数值巧合正确,但逻辑错误会导致多字节大整数计算失败,且程序稳定性差)

问题分析与修复

1. 未定义符号result导致内存访问异常

原代码中使用了未在.data段定义的result符号,汇编链接时会将其解析为不确定的内存地址,导致程序行为不稳定(有时误打误撞访问到合法内存,有时则破坏其他数据)。应将result替换为已定义的quotient。

2. Read系统调用错误处理不严谨

原代码仅检查read返回值是否<=0,但未验证是否读取到完整的64字节。若输入数据不完整,程序会使用未初始化的内存进行计算,导致错误结果。需添加读取字节数的校验。

3. 重复减法算法逻辑完全错误

原代码按单个字节独立执行减法,这不符合大整数除法的逻辑。正确的重复减法应针对整个32字节的大整数进行操作:循环将被除数减去除数,每成功减一次商加1,直到被除数小于除数,此时的被除数即为余数。

修复后的代码

EXIT_NR  = 1
READ_NR  = 3
WRITE_NR = 4

STDOUT = 1
STDIN = 0

EXIT_CODE_SUCCESS = 0
EXIT_CODE_ERROR = 1

.data
dividend: .space 32
divisor:  .space 32
quotient: .space 32
rest:     .space 32

.text
.global _start
_start:
read:
    # 读取64字节:32字节被除数 + 32字节除数
    movl $READ_NR, %eax
    movl $STDIN, %ebx
    movl $dividend, %ecx
    movl $64, %edx
    int $0x80

    # 检查读取是否成功且完整
    cmpl $64, %eax
    jne exit_error

    # 初始化商为0
    movl $0, %edi
clear_quotient:
    movb $0, quotient(%edi)
    incl %edi
    cmpl $32, %edi
    jne clear_quotient

    # 将被除数复制到余数(后续操作余数)
    movl $0, %edi
copy_dividend_to_rest:
    movb dividend(%edi), %al
    movb %al, rest(%edi)
    incl %edi
    cmpl $32, %edi
    jne copy_dividend_to_rest

div_loop:
    # 比较余数和除数:余数 >= 除数则继续减
    call compare_rest_divisor
    jl done_div

    # 余数 = 余数 - 除数
    call subtract_divisor_from_rest

    # 商 += 1(32字节大整数加1)
    call increment_quotient

    jmp div_loop

done_div:
    # 输出商(32字节)+余数(32字节)
    movl $WRITE_NR, %eax
    movl $STDOUT, %ebx
    movl $quotient, %ecx
    movl $64, %edx
    int $0x80

    jmp read

exit_error:
    movl $EXIT_NR, %eax
    movl $EXIT_CODE_ERROR, %ebx
    int $0x80

end:
    movl $EXIT_NR, %eax
    movl $EXIT_CODE_SUCCESS, %ebx
    int $0x80

# 辅助函数:比较rest和divisor(大整数),rest >= divisor则CF=0,否则CF=1
compare_rest_divisor:
    movl $31, %esi
compare_loop:
    movb rest(%esi), %al
    movb divisor(%esi), %bl
    cmpb %bl, %al
    jg compare_ge
    jl compare_lt
    dec %esi
    jns compare_loop
    # 两数相等
    clc
    ret
compare_ge:
    clc
    ret
compare_lt:
    stc
    ret

# 辅助函数:rest = rest - divisor(带借位的大整数减法)
subtract_divisor_from_rest:
    movl $31, %esi
    clc
subtract_loop:
    movb rest(%esi), %al
    sbbb divisor(%esi), %al
    movb %al, rest(%esi)
    dec %esi
    jns subtract_loop
    ret

# 辅助函数:quotient += 1(大整数加1)
increment_quotient:
    movl $31, %esi
    clc
inc_loop:
    movb quotient(%esi), %al
    adcb $1, %al
    movb %al, quotient(%esi)
    jnc inc_done
    dec %esi
    jns inc_loop
inc_done:
    ret

说明

修复后的代码实现了正确的32字节大整数重复减法除法:

  • 严格校验输入读取的完整性,避免未初始化内存访问
  • 采用大整数比较、减法、自增的辅助函数实现核心逻辑
  • 修复了符号未定义的问题,确保内存访问合法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:24:53