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

汇编语言:如何正确输出字符串中出现次数最多的字符

问题分析与修复

你的代码存在三个核心问题,导致字符显示异常:

1. 计数数组的定义与访问不匹配

你将counts定义为resb 256(256字节),但代码中访问计数时使用了eax *4的偏移(比如inc byte [counts + eax *4]),并且在查找最大值时按双字(4字节)读取数据。这会导致:

  • 内存越界:当字符ASCII值超过63时(63*4=252,接近256字节边界),后续访问会超出counts的分配空间。
  • 计数读取错误:按双字读取字节数组会把连续4个字节当成一个计数,导致数值错误。

修复:将counts改为双字数组:

counts              resd 256     ; 每个元素是4字节的计数,对应一个ASCII字符

2. max_char赋值错误

在find_max_loop中,你错误地将计数值的低字节存入max_char(mov [max_char], al),但此时eax存储的是当前字符的出现次数,而非字符本身的ASCII码。这就是为什么输出时显示带框问号——你在打印一个非可打印的控制字符(计数值对应的ASCII)。

修复:计算当前计数对应的字符ASCII值:当前edi指向counts数组的某个元素,字符的ASCII值等于(edi - counts)/4(因为每个计数占4字节)。将这个值存入max_char:

; Update max_char and max_count
mov eax, [edi]
mov ebx, edi
sub ebx, counts       ; ebx = 当前元素的偏移量
shr ebx, 2            ; 偏移量除以4,得到字符的ASCII值
mov [max_char], bl    ; 存入max_char
mov dword [max_count], eax

3. fgets参数错误

fgets的第二个参数是缓冲区的最大长度,你传入了string_length(仅100字节),但input_string分配了256字节。这会导致输入超过100字符时被截断,甚至可能引发缓冲区溢出。

修复:直接传入input_string的大小256:

push dword [stdin]
push dword 256        ; 缓冲区大小
push input_string
call fgets
add esp, 12

修正后的完整代码

%include "asm_io.inc"

section .data
    dash                db "-------------------------------------------------", 0
    progTitle           db "Find the maximum occurring character in a string", 0
    enter_string_prompt db "Enter a string: ", 0
    output_format       db "The highest frequency of character '%c' appears number of times is %d",0

section .bss
    input_string        resb 256
    max_char            resb 1
    max_count           resd 1
    counts              resd 256     ; 每个元素是4字节的计数,对应一个ASCII字符

section .text
    extern printf, fgets, stdin
    global asm_main

asm_main:
    push ebp
    mov ebp, esp

    mov eax, dash
    call print_string
    call print_nl
    mov eax, progTitle
    call print_string
    call print_nl
    mov eax, dash
    call print_string

    call print_nl

    ; prompt
    mov eax, enter_string_prompt
    call print_string

    push dword [stdin]
    push dword 256
    push input_string
    call fgets
    add esp, 12

    mov esi, input_string

count_loop:
    movzx eax, byte [esi]
    cmp al, 0
    je end_count_loop

    ; Skip counting spaces
    cmp al, ' '
    je skip_increment

    inc dword [counts + eax * 4]  ; 按双字计数

skip_increment:
    inc esi
    jmp count_loop

end_count_loop:
    mov ecx, 256
    mov edi, counts
    mov eax, [edi] ; Initialize eax with the first count
    ; 初始化max_char为第一个字符(ASCII 0)
    mov byte [max_char], 0
    mov dword [max_count], eax

find_max_loop:
    cmp dword [edi], eax
    jl next_char

    ; Update max_char and max_count
    mov eax, [edi]
    mov ebx, edi
    sub ebx, counts
    shr ebx, 2
    mov [max_char], bl
    mov dword [max_count], eax

next_char:
    add edi, 4
    loop find_max_loop

    movzx eax, byte[max_char]
    push eax
    push dword [max_count]
    push output_format
    call printf
    add esp, 12

    call print_nl

    leave
    ret

额外说明

  • 初始化max_char时添加了mov byte [max_char], 0,确保初始状态有合法的字符值。
  • 计数时改为inc dword [counts + eax *4],匹配双字数组的访问方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 07:15:06