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

Ubuntu Eclipse C++下ASM的IMUL指令处理数组负数相乘结果异常

Hey there! Let's break down why your IMUL instruction is spitting out that wonky -1210688460 value instead of the expected result when multiplying negative elements in your array. That weird number screams either a memory access mistake, a register mismatch between your C++ code and assembly, or a misalignment between data types and IMUL's operation size.

Common Culprits to Check

Let's walk through the most likely issues:

  1. Mismatched Data Type Sizes & Scaling Factors
    On Ubuntu x86_64, a C++ int is 32 bits (4 bytes). If your assembly code is treating array elements as 64-bit values (using 8-byte scaling for memory addresses), you're reading/writing to the wrong memory locations. For example:

    • ❌ Wrong: mov (%rdi, %rcx, 8), %eax (uses 8-byte steps, which is for long not int)
    • ✅ Correct: mov (%rdi, %rcx, 4), %eax (4-byte steps match the size of int)
      Using the wrong scaling factor will pull garbage data from adjacent memory, which explains that nonsensical negative value.
  2. x86_64 System V Calling Convention Mistakes
    Ubuntu uses the System V calling convention for x86_64, which dictates how arguments are passed to functions:

    • 1st argument (array pointer) → rdi
    • 2nd argument (array size) → rsi
    • 3rd argument (inum) → rdx
      If you're using the wrong register to fetch inum (e.g., using ecx instead of edx), you're multiplying your negative element by a random garbage value from an uninitialized register—leading to that overflow-like result.
  3. Incorrect IMUL Usage & Register Handling

    • For 32-bit int values, use 32-bit registers (eax, edx) with IMUL. If you accidentally use 64-bit registers (rax, rdx) without truncating the result back to 32 bits, you'll write extra high-order bytes into your 32-bit array elements, corrupting the value.
    • Also, remember that IMUL sets overflow flags if the result exceeds the register size. While -9 * inum should fit in a 32-bit int for reasonable inum values, if you're using an incorrect inum (from a bad register), you could easily trigger overflow.
  4. Caller-Saved vs Callee-Saved Registers
    In System V, registers like rbx, rbp, and r12-r15 are callee-saved—meaning your assembly function must save them to the stack before modifying, then restore them before returning. If you skip this, you'll corrupt the C++ code's context, which could lead to unexpected behavior like incorrect array pointers or inum values.

Example Fixed Assembly Snippet

Here's a quick example that follows all the rules for your use case (assuming your C++ function prototype is void multiply_negatives(int* int_array, int size, int inum);):

global multiply_negatives
multiply_negatives:
    push rbx                ; Save callee-saved register
    mov rcx, 0              ; Initialize loop counter

loop_start:
    cmp rcx, rsi            ; Check if we've reached the end of the array
    jge loop_end

    mov eax, [rdi + rcx*4]  ; Load int_array[rcx] (32-bit, 4-byte step)
    test eax, eax           ; Check if the value is negative (sign bit set)
    jge skip_multiply       ; Skip if non-negative

    imul eax, edx           ; Multiply by inum (stored in edx, 32-bit)
    mov [rdi + rcx*4], eax  ; Save result back to the array

skip_multiply:
    inc rcx                 ; Increment counter
    jmp loop_start

loop_end:
    pop rbx                 ; Restore callee-saved register
    ret

Quick Troubleshooting Steps

  1. Double-check your array addressing code to ensure you're using 4 as the scaling factor for int elements.
  2. Verify you're using the correct registers for function arguments per System V convention.
  3. Make sure you're using 32-bit registers (eax, edx) for all operations involving int values.
  4. Confirm you're saving/restoring callee-saved registers if your assembly modifies them.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:59:21