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

汇编程序循环第二次迭代崩溃问题排查求助

汇编程序段错误排查:循环读取输入并存入数组计算总和

我刚接触汇编语言,编写了一个程序,要求循环5次读取用户输入的数字,将ASCII转换为整数存入intArray数组,同时计算这些数字的总和。代码可以编译链接,但执行到第二次迭代时出现段错误,报错信息如下:

Enter an integer: 49
Enter an integer: 50
zsh: segmentation fault out/solution

以下是我的代码,请帮忙排查问题:

section .bss
    input RESB 10 ; reserve 10 bytes for input

section .data
    list db 1,2,3,4,5
    prompt db "Enter an integer: ", 0
    prompt_len equ $ - prompt ; length of the prompt

    result_msg db "The sum is: ", 0
    result_msg_len equ $ - result_msg

    buffer db 12 dup(0)     ; buffer for input
    intArray dd 5 dup(0)
    arraySize db 0
    sum dd 0

section .text

global _start
_start:
    mov ecx, 5 ; loop 5 times

loop_prompt_handler:
    ; print the prompt to enter input
    mov eax, 4              ; sys_write
    mov ebx, 1              ; file descriptor 1 (stdout)
    mov ecx, prompt         ; message to print
    mov edx, prompt_len     ; number of bytes to read
    int 0x80

    ; read the input
    mov eax, 3              ; sys_read
    mov ebx, 0              ; file descriptor 0 (stdin)
    mov ecx, input          ; message to read
    mov edx, 10             ; number of bytes to read
    int 0x80

    ; convert ASCII input to integer
    call str_to_int

    ; append to array
    mov ebx, [arraySize]    ; load current size of the array
    mov edx, intArray       ; load address of the array
    add edx, ebx            ; point to the end of the array
    mov [edx], eax          ; store the input number at the end of the array

    ; increment array size
    inc byte [arraySize]    ; increment array size

    ; add the input number to the sum
    add dword [sum], eax

    loop loop_prompt_handler ; loop_prompt_handler label if ecx is not zero

    ; print the result
    mov eax, 4              ; sys_write
    mov ebx, 1              ; file descriptor 1 (stdout)
    mov ecx, result_msg     ; message to print
    mov edx, result_msg_len ; number of bytes to read
    int 0x80

    ; convert sum to string
    mov eax, [sum]
    mov ecx, buffer         ; buffer containing the sum as a string
    call int_to_string

    ; print the sum
    mov eax, 4              ; sys_write
    mov ebx, 1              ; file descriptor 1 (stdout)
    mov edx, 12             ; length of the buffer
    int 0x80

    ; exit
    mov eax, 1              ; sys_exit
    xor ebx, ebx            ; exit code
    int 0x80

str_to_int:
    ; ecx: pointer to input string
    ; eax: result
    xor eax, eax            ; clear eax
    xor edx, edx            ; clear edx

    str_to_int_loop:
        movzx edx, byte [ecx]
        test dl, dl
        jz str_to_int_end
        sub dl, '0'
        imul eax, eax, 10
        add eax, edx
        inc ecx
        jmp str_to_int_loop
    
    str_to_int_end:
        ret

int_to_string:
    ; eax contains the string to convert
    ; ecx points to the buffer to store the string
    mov edi, ecx
    add edi, 11
    mov byte [edi], 0
    dec edi

    .convert_loop:
        xor edx, edx
        mov ebx, 10
        div ebx
        add dl, '0'
        mov [edi], dl
        dec edi
        test eax, eax
        jnz .convert_loop

    inc edi
    mov ecx, edi
    ret

问题根源及修复方案

1. str_to_int函数参数未正确传入

你在注释中说明ecx是输入字符串指针,但调用str_to_int前,ecx被sys_write和sys_read修改为prompt和input后,没有显式把input地址重新加载到ecx,导致函数读取错误内存地址,触发段错误。

修复:调用str_to_int前添加地址传递代码:

; convert ASCII input to integer
mov ecx, input  ; 将输入缓冲区地址传入ecx
call str_to_int

2. 数组偏移计算错误

intArray是dd类型(每个元素占4字节),但你用单字节类型的arraySize直接偏移数组地址,每次只移动1字节而非4字节,导致数组元素越界覆盖,触发内存访问错误。

修复:

  • 将arraySize改为双字类型:
    ; 修改.data段的定义
    arraySize dd 0
    
  • 计算数组偏移时按4字节步长计算:
    ; append to array
    mov ebx, [arraySize]    ; 加载当前元素个数
    mov edx, intArray       ; 数组基地址
    lea edx, [edx + ebx*4]  ; 计算第ebx个元素的地址(每个元素4字节)
    mov [edx], eax          ; 存储转换后的整数
    

3. 未处理输入中的换行符

用户输入后按回车,sys_read会将换行符(0x0A)读入缓冲区,str_to_int会把它当成非数字字符处理,导致转换逻辑异常。

修复:在str_to_int循环中判断并终止换行符的处理:

str_to_int_loop:
    movzx edx, byte [ecx]
    test dl, dl
    jz str_to_int_end
    cmp dl, 0x0A  ; 判断是否为换行符
    jz str_to_int_end
    sub dl, '0'
    ; 后续代码不变

4. 打印总和时的长度错误

打印总和时直接使用固定长度12,但int_to_string返回的ecx是字符串起始地址,需要计算实际长度才能正确打印。

修复:打印前计算字符串长度:

; print the sum
mov eax, 4              ; sys_write
mov ebx, 1              ; file descriptor 1 (stdout)
; ecx已为字符串起始地址
mov edx, buffer + 12    ; 缓冲区末尾地址
sub edx, ecx            ; 计算字符串实际长度
int 0x80

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:53:17