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

x86汇编中带符号64位乘法与128位除法函数实现求助

Great question! Adapting your unsigned MASM arithmetic functions to signed versions requires understanding how x86-64 handles signed integer operations and aligning with MSVC's calling convention (since you're using Visual Studio). Let's walk through both implementations step by step:

Signed 64-bit Multiplication (128-bit Result)

For signed multiplication, we leverage the imul instruction (instead of unsigned mul), which natively handles sign extension and produces a 128-bit signed result in rdx:rax—perfect for returning a __int128 in MSVC.

C++ Function Declaration

__int128 mul_s64(int64_t a, int64_t b);

MASM Implementation

.code
mul_s64 proc
    ; MSVC calling convention: rcx = first operand (a), rdx = second operand (b)
    mov rax, rcx        ; Load first operand into rax
    imul rdx            ; Signed multiply rax * rdx → result stored in rdx:rax
    ; MSVC uses rdx:rax to return __int128 values, so we can directly return
    ret
mul_s64 endp
end

Key Notes

  • imul automatically handles sign extension for the 128-bit result, so no extra logic is needed to adjust the sign of the product.
  • This matches the behavior of C++'s built-in signed multiplication, including overflow handling (which wraps around per two's complement rules).

Signed 128-bit Division (128-bit Quotient + 32-bit Remainder)

Signed division is trickier because we need to ensure the quotient's sign is the XOR of the dividend and divisor's signs, and the remainder's sign matches the dividend. We'll use the idiv instruction, which handles signed division of a 128-bit dividend (rdx:rax) by a 64-bit divisor.

C++ Function Declaration

__int128 div_s128(__int128 dividend, int64_t divisor, int32_t* remainder);

MASM Implementation

.code
div_s128 proc
    ; MSVC calling convention breakdown:
    ; rcx = dividend (low 64 bits), rdx = dividend (high 64 bits)
    ; r8 = divisor, r9 = pointer to store 32-bit remainder
    push rbx            ; Save non-volatile register (required by MSVC convention)
    mov rbx, r9         ; Store remainder pointer in rbx for later use

    ; Set up dividend in rdx:rax (already aligned with MSVC's __int128 parameter passing)
    mov rax, rcx        ; Load low 64 bits of dividend into rax
    ; rdx already holds the high 64 bits (sign-extended for __int128)

    idiv r8             ; Signed division: rdx:rax ÷ r8 → rax=quotient, rdx=remainder
                        ; Remainder will have the same sign as the dividend

    ; Extend 64-bit quotient to 128-bit signed value
    mov rdx, 0
    test rax, rax       ; Check if quotient is positive (bit 63 is 0)
    jns quotient_positive
    mov rdx, 0FFFFFFFFFFFFFFFFh  ; Sign-extend negative quotient to 128 bits
quotient_positive:

    ; Prepare 32-bit remainder (sign-extend to match int32_t)
    mov eax, edx        ; Grab low 32 bits of the 64-bit remainder
    cdq                 ; Sign-extend eax to edx:eax (ensures correct negative representation)
    mov [rbx], eax      ; Store the signed 32-bit remainder in the output pointer

    pop rbx             ; Restore non-volatile register
    ret                 ; Return 128-bit quotient in rdx:rax
div_s128 endp
end

Key Notes

  • Sign Handling: idiv automatically computes the correct quotient and remainder signs, so we don't need to manually flip signs (unlike manual unsigned-to-signed conversion approaches).
  • 128-bit Quotient: Since a 128-bit dividend divided by a 64-bit divisor can only produce a 64-bit quotient, we sign-extend it to 128 bits by setting rdx to all 1s for negative values or 0 for positive values.
  • 32-bit Remainder: We truncate the 64-bit remainder to 32 bits and use cdq to ensure proper sign extension for the int32_t type.
  • Boundary Cases: Be sure to handle division by zero in your C++ caller (the assembly will throw an exception if divisor is 0) and overflow scenarios (e.g., INT128_MIN ÷ -1, which exceeds INT128_MAX).

内容的提问来源于stack exchange,提问作者b.sullender

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:31:41