C转汇编求助:ChangeVector函数改写后输出结果异常
问题描述
需要将changeVector函数改写为不使用变量、且必须包含push ebp/mov ebp, esp栈帧指令的汇编代码。原C代码运行正常,但自行编写的汇编版本无论输入是什么,输出始终固定为0xFFFFFFFE 0X0000000C,结果完全错误。
例如测试用例:
- n=2,向量元素为
-2、12 - i=1,k=5,v=1
正确输出应为0XFFFFFFFF 0X0842108c,但汇编实现无法得到该结果。
原C代码
void changeBit(unsigned int *vector, int indice, int valor) { int posicion = indice / 32; // 找到位所在的向量元素位置 int bit = 31 - (indice % 32); // 找到元素内的具体位偏移 __asm { mov esi, vector mov edi, posicion mov ecx, bit mov eax, dword ptr [esi + edi * 4] ; 加载当前向量元素的值 cmp valor, 0 jne set_bit ; 若值不为0则跳转到置位逻辑 btr [esi + edi * 4], ecx ; 将指定位清零 jmp done set_bit: mov edx, 1 shl edx, cl ; 将1移到目标位的位置 or dword ptr [esi + edi * 4], edx ; 用OR操作置位 done: } } void changeVector(unsigned int *vector, int n, int i, int k, int v) { // 循环处理从i开始、步长为k的所有位,直到超出向量总位数 for (int j = 0; (i + j * k) < n * 32; j++) { changeBit(vector, (i + j * k), v); // 调用位修改函数 } } int main() { int n; do { printf("Enter the size of the vector (n): "); scanf("%d", &n); if (n <= 0) { printf("The size of the vector must be greater than 0. Please try again.\n"); } } while (n <= 0); unsigned int *vector = (unsigned int *)calloc(n, sizeof(unsigned int)); if (vector == NULL) { printf("Error allocating memory for the vector.\n"); return 1; } printf("Enter values for each element of the vector:\n"); for (int i = 0; i < n; i++) { printf("Enter the value of the element: "); scanf("%u", &vector[i]); } int i, k, v; printf("Enter the initial index (i): "); scanf("%d", &i); printf("Enter the step (k): "); scanf("%d", &k); printf("Enter the value (v, 0 or 1): "); scanf("%d", &v); printf("The original unsigned int vector (size %d) would be:\n", n); for (int i = 0; i < n; i++) { printf("0x%08X \n", vector[i]); } changeVector(vector, n, i, k, v); printf("\nAfter the assignment, the vector is:\n"); for (int i = 0; i < n; i++) { printf("0x%08X \n", vector[i]); } free(vector); return 0; }
自行编写的错误汇编代码
void changeVector(unsigned int *vector, int n, int i, int k, int v) { __asm { mov esi, vector ; 向量地址 mov ecx, n ; 向量元素个数 mov edx, i ; 初始索引 mov ebx, k ; 步长 loop_start: cmp edx, ecx ; 比较索引与向量大小 jge loop_end ; 若索引 >= 大小则退出循环 ; 根据当前索引(edx)计算位索引 mov eax, edx ; 将索引复制到eax imul eax, 32 ; 索引乘以32 mov edi, eax ; 保存结果到edi ; 调用changeBit函数,传入计算后的位索引(edi)和值(v) push v push edi push esi call changeBit add esp, 12 ; 函数调用后清理栈 ; 根据步长(ebx)更新索引(edx) add edx, ebx jmp loop_start ; 跳回循环开始 loop_end: } }
问题分析与修复
你的汇编代码存在三个核心错误,导致结果完全偏离预期:
1. 循环条件完全错误
原C代码的循环条件是当前处理的位索引 < 向量总位数(即(i + j*k) < n*32),但你的汇编里直接比较edx(当前位索引)和ecx(向量元素个数n),相当于用位索引和元素个数比,完全不符合逻辑。
2. 错误放大了位索引
原C中changeBit的第二个参数就是原始位索引(比如测试用例中的1、6、11...),但你额外做了imul eax,32,把位索引乘以32,导致传入changeBit的索引是正确值的32倍,直接修改了完全无关的内存位置。
3. 未遵循栈帧要求与寄存器调用约定
你没有添加push ebp/mov ebp, esp的栈帧指令,同时ebx是非易失性寄存器(调用者需要保存),直接修改会破坏上层函数的上下文。
修复后的汇编代码
void changeVector(unsigned int *vector, int n, int i, int k, int v) { __asm { ; 建立栈帧 push ebp mov ebp, esp ; 保存非易失性寄存器(ebx) push ebx ; 从栈帧中获取函数参数 mov esi, [ebp+8] ; vector 参数 mov ecx, [ebp+12] ; n 参数 mov edx, [ebp+16] ; i 参数(初始位索引) mov ebx, [ebp+20] ; k 参数(步长) mov eax, [ebp+24] ; v 参数 ; 计算向量总位数:n * 32,保存到edi mov edi, ecx imul edi, 32 loop_start: ; 循环条件:当前位索引(edx) < 总位数(edi) cmp edx, edi jge loop_end ; 调用changeBit:参数顺序是vector, 位索引(edx), v(eax) push eax push edx push esi call changeBit add esp, 12 ; 清理栈上的3个参数 ; 更新位索引:edx += k(ebx) add edx, ebx jmp loop_start loop_end: ; 恢复非易失性寄存器 pop ebx ; 销毁栈帧 pop ebp } }
修复说明
- 严格按照要求添加了栈帧的建立与销毁指令
- 修正循环条件:用当前位索引和总位数
n*32比较 - 移除了错误的位索引乘32操作,直接将当前位索引传入
changeBit - 保存并恢复了非易失性寄存器
ebx,符合x86调用约定 - 从栈帧中获取参数,贴合“不使用变量”的要求
内容的提问来源于stack exchange,提问作者Leah M
相关产品推荐
相关产品推荐

