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

x86 GAS汇编调用异常排查:为何执行asm_function出现段错误?

调用汇编函数出现段错误且无返回值的原因及修复

一、C代码里的致命错误

  • 内存分配错误:create_array里用malloc(sizeof(array)),array是指针类型,32位系统下只会分配4字节,64位是8字节,但你要存size=10个int,应该改成malloc(sizeof(int) * size),否则数组越界直接触发内存访问错误。
  • 循环初始化与范围问题:循环从i=1开始,array[0]未初始化;且循环条件i < size,当size=10时,会给array[1]到array[9]赋值,但原分配的空间根本不够,进一步加剧越界问题。

二、汇编代码里的核心错误

  • 参数顺序完全搞反:C的cdecl调用约定中,参数是从右往左压栈,所以asm_function(index, size, data)的栈布局是:
    • 8(%ebp) → 第一个参数index
    • 12(%ebp) → 第二个参数size
    • 16(%ebp) → 第三个参数data
      但你汇编里把8(%ebp)当成data、16(%ebp)当成index,直接导致访问了错误的内存地址,这是段错误的直接原因。
  • 无效的内存访问:movl (%ecx, %edi, 4), %edx这行,因为参数拿反了,实际是用index作为基址、size作为索引计算地址,完全不是你要访问的data[index],必然触发非法内存访问。
  • 返回值逻辑混乱:循环里movl %esi, %eax只是把循环变量i赋值给返回寄存器,但这和你调用函数想要获取的data[index]逻辑无关,最后返回的是循环结束后的i值,完全不符合预期。

三、修正后的代码

修正后的C代码

#include <stdio.h>
#include <stdlib.h>

extern int asm_function(int index, int size, int* data);

int *create_array(int size){
    // 分配足够的内存并初始化所有元素为0
    int *array = calloc(size, sizeof(int));
    for(int i = 0; i < size; i++){
        array[i] = i;
    }
    return array;
}

int main(int argc, char **argv) {
    int index = 5;
    int size = 10;
    int *data = create_array(size);
    int value = asm_function(index, size, data);
    printf("Value %d\n", value);
    // 释放内存避免泄漏
    free(data);
    return 0;
}

修正后的汇编代码(32位x86,cdecl约定)

FUNC(asm_function):
    pushl %ebp
    movl %esp, %ebp

    // 保存非易失性寄存器
    pushl %ebx
    pushl %esi
    pushl %edi

    // 正确读取参数:index(8), size(12), data(16)
    movl 8(%ebp), %ecx    ; ecx = index
    movl 16(%ebp), %ebx   ; ebx = data
    ; 计算 data[index] = *(ebx + ecx*4),存入eax作为返回值
    movl (%ebx, %ecx, 4), %eax

    // 保留原循环逻辑(若需要遍历数组),已修正参数引用
    movl $1, %esi         ; i = 1
loops:
    cmpl 12(%ebp), %esi   ; 比较i和size
    jge exit              ; i >= size则退出循环
    movl %esi, (%ebx, %esi, 4) ; array[i] = i
    incl %esi
    jmp loops

exit:
    // 恢复寄存器
    popl %edi
    popl %esi
    popl %ebx
    popl %ebp
    ret

四、关键说明

修正后汇编首先正确读取了参数,把data[index]加载到eax(x86下返回值存在eax寄存器),同时C代码修复了内存分配和循环问题,运行后会正确返回data[5]的值5(若保留循环,数组元素会被重新赋值,但返回值仍为初始设定的data[5])。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:40:30