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

基于Linux命令dc的C语言计算器汇编除法函数负数处理问题

Fixing Signed Division Issues in Your Assembly Division Function

Looks like your assembly division routine is only handling unsigned integers right now, which is why negative values are producing garbage results. Let's break down what's happening and fix it.

The Root Cause

You're almost certainly using the div instruction in your assembly code. This instruction treats all operands as unsigned numbers. For example:

  • -999 in 32-bit two's complement is 0xFFFFFF9D
  • When you run 0xFFFFFF9D / 3 as an unsigned calculation, you get 0x55555532—which is exactly the 1431655432 you're seeing as the wrong result.

Negative numbers need special handling with signed division instructions and proper sign extension.

The Fix: Use Signed Division Instructions

To handle signed integers, you need to:

  1. Use the idiv instruction (instead of div)
  2. Extend the sign bit of your dividend to match the size of the division operation (so the CPU recognizes it as a signed value)

Example 32-bit Assembly Function (x86)

If you're targeting 32-bit systems, here's a corrected division routine that follows the C cdecl calling convention:

.global div_signed
div_signed:
    # Get parameters from stack: [esp+4] = dividend, [esp+8] = divisor
    mov eax, [esp+4]   # Load dividend into EAX
    cdq                # Sign-extend EAX to EDX:EAX (critical for signed division)
    idiv dword [esp+8] # Divide EDX:EAX by divisor; quotient stays in EAX
    ret                # Return quotient in EAX (matches C's int return convention)

Example 64-bit Assembly Function (x86-64)

For 64-bit Linux (using System V AMD64 ABI, where arguments are passed in RDI, RSI):

.global div_signed
div_signed:
    mov rax, rdi       # Move dividend from RDI to RAX
    cqo                # Sign-extend RAX to RDX:RAX
    idiv rsi           # Divide RDX:RAX by divisor in RSI; quotient in RAX
    ret                # Return quotient in RAX

Integrating with Your C Code

Call the assembly function from C like this (adjust types for 32/64-bit):

#include <stdio.h>

// For 32-bit:
extern int div_signed(int dividend, int divisor);

// For 64-bit:
// extern long div_signed(long dividend, long divisor);

int main() {
    printf("-999 / 3 = %d\n", div_signed(-999, 3));   // Should output -333
    printf("-999 / -3 = %d\n", div_signed(-999, -3)); // Should output 333
    return 0;
}

Key Notes

  • Divisor Check: Don't forget to add a check in your C code (or assembly) for a divisor of 0—idiv will trigger a CPU exception if you divide by zero.
  • Calling Convention: Make sure your assembly matches the C calling convention of your target platform (cdecl for 32-bit Linux, System V AMD64 for 64-bit).
  • Unsigned vs Signed: Keep using div if you need unsigned division, but switch to idiv + sign extension for signed values.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:58:29