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

如何编写NASM汇编文件实现高精度除法?现有代码问题求助

NASM高精度除法:greater_eq与mydiv函数问题排查与修正建议

我想用NASM实现高精度除法,先编写了一份C代码作为参考,目前已完成读、写及字符串反转功能,但greater_eq和mydiv函数存在逻辑错误,急需修正方案。


参考C代码

#include <cstdio>
#include <cstring>

static const int LEN = 1004;

int a[LEN], b[LEN], c[LEN], d[LEN];
void clear(int a[])
{
    for (int i = 0; i < LEN; ++i)
        a[i] = 0;
}

void read(int a[])
{
    static char s[LEN + 1];
    int x=0;
    int c=getchar();
    while (c!='\n' && x<LEN-1)
    {
        s[x++] = c;
        c = getchar();
    }
    s[x]='\0';
    clear(a);
    int len = strlen(s);
    for (int i = 0; i < len; ++i)
        a[len - i - 1] = s[i] - '0';
}

void print(int a[])
{
    int i;
    for (i = LEN - 1; i >= 1; --i)
        if (a[i] != 0)
            break;
    for (; i >= 0; --i)
        putchar(a[i] + '0');
    putchar('\n');
}


int greater_eq(int a[], int b[], int last_dg, int len)
{
    if (a[last_dg + len] != 0){
        printf("1!");
        return 1;
    }
        
    for (int i = len - 1; i >= 0; --i)
    {
        if (a[last_dg + i] > b[i]){
            printf("2!");
            return 1;}
        if (a[last_dg + i] < b[i]){
            printf("3!");
            return 0;}
    }
    printf("4!");
    return 1;
}

void div(int a[], int b[], int c[], int d[])
{
    clear(c);
    clear(d);

    int la, lb;
    for (la = LEN - 1; la > 0; --la)
        if (a[la - 1] != 0)
            break;
    for (lb = LEN - 1; lb > 0; --lb)
        if (b[lb - 1] != 0)
            break;
    if (lb == 0)
    {
        puts("> <");
        return;
    }

    for (int i = 0; i < la; ++i)
        d[i] = a[i];
    for (int i = la - lb; i >= 0; --i)
    {
        while (greater_eq(d, b, i, lb))
        {
            for (int j = 0; j < lb; ++j)
            {
                d[i + j] -= b[j];
                if (d[i + j] < 0)
                {
                    d[i + j + 1] -= 1;
                    d[i + j] += 10;
                }
            }
            c[i] += 1;
        }
    }
}

int main()
{
    read(a);
    read(b);
    div(a, b, c, d);
    print(c);
    print(d);
}

我的NASM数据定义

num1 times 100 db '0',0h 
num2 times 100 db '0',0h

问题函数1:greater_eq

greater_eq:
    ;a[]:num1,b[]:num2,last_ag:eax,len:ebx
    ;return in eax
    push ecx
    push edx
    push esi; preserve values
    mov esi,num1
    add esi,eax
    add esi,ebx ;a[last+len]
    cmp [esi],‘0’
    je compare
    jne greater

compare:
    mov ecx,ebx ;i=len-1
    dec ecx

.loop:
    cmp ecx,0h 
    jl greater
    mov esi,eax
    add esi,ecx
    mov edx,[num1+esi] ;a[last_eg+i]
    cmp edx,[num2+ecx] ;b[i]
    jg greater
    jl lesser
    dec ecx
    jmp .loop

greater:
    pop esi
    pop edx
    pop ecx
    
    mov eax,1
    ret
lesser:
    pop esi
    pop edx
    pop ecx
    mov eax,0
    ret

问题函数2:mydiv

mydiv:
    mov eax,sinput
    call strlen
    mov ecx,eax
    ;la ecx
    mov eax,dinput
    call strlen
    mov edx,eax
    ;lb edx
    jz rerurn_diff

    mov eax,sinput
    mov ebx,dinput

    mov esi,ecx ;i=0
    sub esi,edx ;i=la-lb
div_loop:
    cmp esi,0  
    jl  return_n  ; i<0结束循环
    
div_continue:
    push eax
    push ebx
    mov eax,esi  ;i
    mov ebx,edx  ;lb
   
    call greater_eq
    mov ebp,eax  ;res
    pop ebx
    pop eax
    
    cmp ebp,0
    jne div_sub
   
    dec esi ;i--
    jmp div_loop

div_sub:
    mov edi,0 ;j=0
div_sub_loop:
    cmp edi,edx ;j>=lb 退出
    jge div_sub_add
    push ebp
    mov ebp,eax
    add ebp,esi
    add ebp,edi; a[i+j] ->byte[eax+esi+edi]
   ;1
  
    
    push ebx
    add ebx,edi
    push eax
    mov ah,byte[ebp]
    mov al,byte[ebx]
    sub ah,al  ;a[i+j] -= b[j]
    mov byte[ebp],ah
    pop eax
    pop ebx

    ;2
    
    cmp byte[ebp],0
    jl div_loop_fix
div_sub_con:
    pop ebp
    inc edi ;j++
    inc byte[c+esi] ;c[i]++
    
    jmp div_continue

div_loop_fix:
    dec byte[ebp+1]
    add byte[ebp],10
    jmp div_sub_con
div_sub_add:
    inc byte[c+esi]
    jmp div_continue

return_n:
    ret
rerurn_diff:
    mov eax,meg6
    ret

核心问题与修正方案

针对greater_eq的修正点

  1. 字符与数值混淆:C代码数组存储的是0-9的数值,但你的NASM中num1/num2存储的是'0'-'9'的ASCII字符,比较时必须先转成数值(减去'0'),否则是比较ASCII值,逻辑完全错误。
    • 示例修正:将cmp [esi],‘0’改为mov al, [esi] sub al, '0' cmp al, 0;比较a[last_dg+i]和b[i]时,同样先转成数值再比较。
  2. 循环边界校验:当前代码中cmp ecx,0h jl greater逻辑正确,但需确保每次循环都正确获取对应位置的数值,而非字符。
  3. 寄存器顺序:pop操作必须和push顺序相反(后进先出),当前代码顺序正确,无需修改。

针对mydiv的修正点

  1. 存储逻辑对齐C代码:必须将输入字符串转换为逆序数值数组(和C的read函数逻辑一致),用字节存储0-9的数值,而非直接操作字符串。
  2. 减法与借位逻辑修正:
    • C代码中是数值减法+借位,你的NASM直接操作字符减法,借位时dec byte[ebp+1]会把字符变成非数值(比如'0'-1='/'),完全错误。必须基于数值数组实现减法:
      ; 示例:数值数组的减法与借位
      mov al, [d+i+j]
      sub al, [b+j]
      mov [d+i+j], al
      cmp al, 0
      jge skip_borrow
      dec byte [d+i+j+1]
      add byte [d+i+j], 10
      skip_borrow:
      
  3. 循环逻辑修正:C代码中是while(greater_eq(...)),每次完整减法后才让c[i]加1,你的NASM在div_sub_loop中每循环一次j就加1,逻辑错误,需将inc byte[c+esi]移到完整减法循环外。
  4. 被除数复制逻辑补充:必须先将被除数数组复制到临时数组d(和C代码一致),再进行除法操作。

快速落地建议

  1. 先确保所有计算用数组(num1、num2、c、d)都是数值数组,从read函数输出时直接转成逆序数值存储。
  2. 完全对齐C代码的逻辑重写greater_eq,直接操作数值字节。
  3. 重写mydiv的核心循环,严格按照C代码的while+减法+借位逻辑实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:27:21