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

32位Intel汇编读取命令行参数异常:触发段错误无输出求助

段错误原因分析与修复方案

核心错误点分析

1. 命令行参数(argv)的栈处理完全错误

程序启动时,栈的初始布局是:

栈顶 → argc
       argv[0] (程序路径)
       argv[1]
       ...
       argv[argc-1]
       NULL

原代码中_start里pop ecx获取argc后,push ecx把argc重新压栈,跳转后通过pop操作取参数的逻辑完全混乱,导致后续取出的是无效内存地址,触发段错误。

2. CDECL调用约定下的栈平衡问题

strncmp遵循CDECL调用约定:参数从右往左压栈,调用者负责清理栈上的参数。原代码调用strncmp后未清理栈上的3个参数(共12字节),导致栈指针错位,后续所有栈操作都指向错误内存区域,直接引发段错误。

3. 字符串变量定义错误

input_syntax : dd "-i"和output_syntax: dd "-o"使用dd(双字,4字节)存储字符串,虽前两个字节正确,但不符合字符串标准存储格式,可能引入多余数据。正确的字符串定义应使用db(字节)。

4. 全局变量语法错误

global Infile: db 0和global Outfile: db 1写法不符合汇编语法,global声明应与变量定义分离,需先声明全局符号再定义变量。


修复后的完整代码

C语言strncmp函数(无需修改)

/*
The strncmp() function is similar to strcmp, 
except it only compares the first (at most) n characters of s1 and s2.
*/
int strncmp(const char* str1, const char* str2, unsigned int n)
{
    while(n--)
    {
        if(*str1++!=*str2++)
        {
            return *(unsigned char*)(str1 - 1) - *(unsigned char*)(str2 - 1);
        }
    }
    return 0;
}

修复后的32位Intel汇编代码

linefeed db 10                  ; 换行符,用db定义字节
input_syntax db "-i", 0         ; 规范定义字符串
output_syntax db "-o", 0

extern strncmp
global _start
global Infile
global Outfile

Infile db 0
Outfile db 1

_start:
    pop ecx                     ; ecx = argc
    mov esi, esp                ; esi = argv数组的起始地址(指向argv[0])
    mov edx, ecx                ; edx 保存argc用于循环计数

loop2:
    cmp edx, 0
    jz end_loop                 ; 计数为0时退出循环

    dec edx
    mov ebx, [esi]              ; ebx = 当前argv元素(char*)
    add esi, 4                  ; 移动到下一个argv元素(32位系统指针占4字节)

    ; 检查是否匹配"-i"前缀
    push 2                      ; 第三个参数:比较长度n=2
    push ebx                    ; 第二个参数:待比较的字符串
    push input_syntax           ; 第一个参数:目标字符串"-i"
    call strncmp
    add esp, 12                 ; 清理栈上的3个参数(3*4=12字节)
    cmp eax, 0
    je print_input

    ; 检查是否匹配"-o"前缀
    push 2
    push ebx
    push output_syntax
    call strncmp
    add esp, 12
    cmp eax, 0
    je print_output

    jmp loop2                   ; 不匹配则继续循环

print_input:
    mov eax, input_syntax
    mov ebx, 2
    call print_word
    jmp loop2

print_output:
    mov eax, output_syntax
    mov ebx, 2
    call print_word
    jmp loop2

end_loop:
    ; 退出程序
    mov eax, 1
    mov ebx, 0
    int 0x80

print_word:                     ; eax = 字符串指针, ebx = 长度
    mov ecx, eax
    mov edx, ebx
    mov eax, 4                  ; sys_write
    mov ebx, 1                  ; stdout
    int 0x80

    ; 打印换行
    mov eax, 4
    mov ebx, 1
    mov ecx, linefeed
    mov edx, 1
    int 0x80

    ret

修复说明

  1. 正确遍历argv:直接通过esi指针遍历argv数组,每次移动4字节(32位指针长度),避免栈操作混乱。
  2. 维护栈平衡:每次调用strncmp后,用add esp, 12清理栈上的3个参数,符合CDECL调用约定。
  3. 规范变量定义:用db定义字符串和换行符,修正全局变量的声明语法。
  4. 简化逻辑:移除原代码中多余的跳转和栈操作,让循环逻辑更清晰,避免无效的内存访问。

测试输入./encoder -i -iewqfra -ods asr时,输出与预期一致:

-i
-i
-o

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:32:04