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

Visual Studio内嵌汇编转独立汇编过程后计数异常排查求助

内嵌汇编转独立__stdcall汇编过程后计数错误排查

原有内嵌汇编的C++程序功能正常,将其重构为独立的__stdcall调用约定汇编过程后出现计数错误,怀疑问题出在loop_2循环中,但无法定位。

可正常运行的内嵌汇编代码

#include <iostream>
int main() {
    const int N = 5; // количество элементов для подсчета количества значений
    int raznost = N / 2; // рассчитывается смещение для отрицательных чисел
    int arr[] = { 1,2,2 };
    int freq[N] = { 0 };
    int n = sizeof(arr) / sizeof(arr[0]);
    int* result = new int[n];
    _asm {
        xor eax, eax
        xor ebx, ebx
        xor ecx, ecx
        lea eax, arr
        lea ebx, freq
        mov edx, raznost

        imul edx, 4
        add ebx, edx
        loop_1 :
        cmp ecx, n
            je loopend_1
            mov edx, [eax + ecx * 4]
            inc[ebx + edx * 4]
            inc ecx
            jmp loop_1
            loopend_1 :
        lea ebx, freq
            xor edx, edx // для количества элементов в новом массиве
            xor ecx, ecx
            outer_loop :
        cmp ecx, n
            je outer_loopend
            push ecx
            xor ecx, ecx // счетчик
            xor eax, eax // максимальное значение
            xor esi, esi // количество
            mov eax, 0
            loop_2:
        cmp ecx, N
            je loopend_2
            cmp esi, [ebx + ecx * 4]
            jg end_if
            mov esi, [ebx + ecx * 4]
            mov eax, ecx
            end_if :
        inc ecx
            jmp loop_2
            loopend_2 :
        xor ecx, ecx
            push ebx
            mov ebx, eax
            push ebx
            mov ebx, result
            sub eax, raznost
            loop_3 :
        cmp esi, ecx
            je loopend_3
            mov[ebx + edx * 4], eax
            inc edx
            inc ecx
            jmp loop_3
            loopend_3:
        pop ebx
            mov ecx, ebx
            pop ebx

            push eax
            mov eax, 0

            mov[ebx + ecx * 4], eax
            pop eax
            pop ecx
            inc ecx
            jmp outer_loop
            outer_loopend:
    }

    for (int i = 0; i < n; i++)
    {
        std::cout << result[i] << " ";
    }
    return 0;
}

运行异常的独立汇编代码

C++调用部分

#include <iostream>
using namespace std;

extern "C" int __stdcall Proc1(int* arr, int* freq, int raznost, int n, int N, int* result);
int main() {
    const int N = 5;//2000; // количество элементов для подсчета количества значений
    int raznost = N / 2; // рассчитывается смещение для отрицательных чисел
    int arr[] = { 1,1,2};
    int freq[N] = { 0 };
    int n = sizeof(arr) / sizeof(arr[0]);
    int* result = new int[n];
    Proc1(arr, freq, raznost, n, N, result);

    for (int i = 0; i < n; i++)
    {
        std::cout << result[i] << " ";
    }
    return 0;
}

汇编实现部分

.386
PUBLIC _Proc1@24

.model flat
.data
.code

_Proc1@24 proc
    push ebp
    mov ebp, esp
    
    xor eax, eax
    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx
    mov eax, [ebp + 8]
    mov ebx, [ebp + 12]
    mov edx, [ebp + 16]

    imul edx, 4
    add ebx, edx
    loop_1 :
    cmp ecx, [ebp + 20]
        je loopend_1
        mov edx, [eax + ecx * 4]
        inc dword ptr [ebx + edx * 4]
        inc ecx
        jmp loop_1
        loopend_1 :
    xor edx, edx ; для количества элементов в новом массиве
    xor ecx, ecx
    outer_loop :
    cmp ecx, [ebp + 20]
        je outer_loopend
        push ecx
        xor ecx, ecx ; счетчик
        xor eax, eax ; максимальное значение
        xor esi, esi ; количество
        mov eax, 0
        loop_2:
    cmp ecx, [ebp + 24]
        je loopend_2
        cmp esi, [ebx + ecx * 4]
        jg end_if
        mov esi, [ebx + ecx * 4]
        mov eax, ecx
        end_if :
        inc ecx
        jmp loop_2
        loopend_2 :
    xor ecx, ecx
        push ebx
        mov ebx, eax
        push ebx
        mov ebx, [ebp + 28]
        sub eax, edx
        loop_3 :
    cmp esi, ecx
        je loopend_3
        mov[ebx + edx * 4], eax
        inc edx
        inc ecx
        jmp loop_3
        loopend_3:
    pop ebx
        mov edi, ebx
        pop ebx
        push eax
        mov eax, 0
        mov [ebx + edi * 4], eax
        pop eax

        pop ecx
        inc ecx
        jmp outer_loop
        outer_loopend:

    mov esp,ebp
    pop ebp
    ret 24
_Proc1@24   endp

end

错误排查结果

  1. loop_1结束后未恢复ebx指向freq初始地址
    内嵌汇编中loopend_1后有lea ebx, freq,将ebx重置为freq数组的起始地址;但独立汇编中没有这一步,此时ebx还是loop_1中偏移后的地址(ebx + raznost*4),导致后续loop_2访问的不是原始freq数组,而是偏移后的错误位置。
    修复:在loopend_1后添加mov ebx, [ebp + 12],重新加载freq的初始地址到ebx。

  2. loop_3中误用edx代替raznost
    内嵌汇编中sub eax, raznost用于还原原始数值,但独立汇编中写成了sub eax, edx,此时edx是用于统计新数组元素数量的变量,不是raznost。需要提前保存raznost的值:
    修复:在函数开头将raznost存入非易失性寄存器(比如edi),例如:

    mov edi, [ebp + 16] ; 保存raznost到edi
    

    然后在loop_3中改为sub eax, edi。

  3. 寄存器保存不符合__stdcall约定
    __stdcall要求函数保存非易失性寄存器(ebp, ebx, esi, edi),当前代码中修改了ebx、esi、edi但未保存,可能导致调用者环境被破坏。
    修复:在函数开头添加push ebx、push esi、push edi,在函数结束前对应pop edi、pop esi、pop ebx。

  4. 未初始化edi却直接使用
    代码中mov edi, ebx使用了edi,但edi未初始化,需要确保寄存器使用前正确赋值或保存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 06:44:56