【问题标题】:getting character from string and using it as array index... ASM从字符串中获取字符并将其用作数组索引... ASM
【发布时间】:2015-02-13 19:47:01
【问题描述】:

无法使用字符串数组并从中获取每个字符并将 1 添加到相应 ascii 索引的频率表中(频率表由 ascii 值索引):例如,获取字符“a”然后将 1 添加到数组 ['a'] 的索引频率表。我收到分段错误,现在收到错误:操作码和操作数的无效组合,谈论mov ax, al 有关问题的参数的任何问题,请询问。我已经为此工作了几个小时,并且真的可以用另一双眼睛来检查我做错了什么(语法/概念如果你看到一个)请帮忙。

更新:我已经把它打印出来了,所以我认为它正在“工作”;但是我现在正在尝试打印每个数组索引对应的字符。它不会打印我指向的数组的字符(它实际上不打印字符)。

最新更新:我让它工作了。更改了标签 .loopa 下的一些代码,现在它可以正常工作了! :) 代码如下:

SECTION .data               ; Data section, initialized variables
 array5:     db "Hello, world...", 0
 array5Len:  equ $-array5-1
 asoutput:   db "%s", 0        ; string output
 newline:    db "", 10, 0      ; format for a new line
 acoutput: db "%c: ", 0                 ; output format for character output

SECTION .bss                   ; BSS, uninitialized variables
 arrayq:     resd 128          ; frequency array of the first 127 ascii values initialized to 0 (none have been counted yet)

SECTION .text
  global main           ; the standard gcc entry point
  main:                 ; the program label for the entry point
    push    ebp         ; set up stack frame
    mov     ebp,esp

    mov esi, array5
    mov edi, 0
    mov ebx, arrayq
    mov ecx, array5Len
; get each character of array5 and add 1 to the frequency table of the corresponding ascii value (which the arrayq is indexed by ascii value).
.loopf:
    xor eax, eax
    mov al, [esi]
    ;mov ax, [esi]
    ;mov ax, al
    ;mov cx, ax
    add edi, eax
    mov ebx, 1
    add [arrayq+4*edi], ebx

    mov edi, 0
    add esi, 1
    loop .loopf

    push dword array2
    push dword asoutput
    call printf
    add esp, 8

    push dword newline
    call printf
    add esp, 4

    ;pop ebx    
    mov ebx, arrayq
    mov ecx, 128                            ; size of arrayq
    mov esi, 0                              ;start at beginning
.loopa:
    mov eax, 0
    cmp [ebx+esi], eax
    je .skip
    mov eax, esi
    push ebx
    push ecx
    mov ebx, 4
    cdq
    div ebx
    push eax
    push dword acoutput
    call printf
    add esp, 8
    pop ecx
    pop ebx

    push ebx
    push ecx                                    ; make sure to put ecx (counter) on stack so we don't lose it when calling printf)
    push dword [ebx + esi]                  ; put the value of the array at this (esi) index on the stack to be used by printf
    push dword aoutput                          ; put the array output format on the stack for printf to use
    call printf                                 ; call the printf command
    add esp, 8                                  ; add 4 bytes * 2
    pop ecx                                     ; get ecx back
    pop ebx

    push ebx
    push ecx
    push dword newline
    call printf
    add esp, 4
    pop ecx
    pop ebx

.skip:
    add esi, 4
    loop .loopa
.end:
    mov     esp, ebp    ; takedown stack frame
    pop     ebp         ; same as "leave" op

【问题讨论】:

  • mov ax, al 不起作用,因为您要求将 8 位值移动到 16 位寄存器。然而,无论如何,这一举动毫无意义,因为alaxeax 都是同一个寄存器,分别只是低 8 位、低 16 位和完整的 32 位。因此,在您的 mov al, [esi] 之后,您可以立即使用 eax 值来索引您的频率表。
  • @500-InternalServerError 感谢解决了程序的那一部分,现在我有一个“稍微”不同的问题......
  • 也许我不明白你的代码,但它不是获取 char 并将其用作 ascii-count-array arrayq 的索引的最简单方法,如下所示:add [arrayq + 4*eax], dword 1?嗯,您需要先用零初始化您的 ascii 计数 arraayq,还是?一个循环:mov ecx, 128mov [arrayq + 4 * ecx], dword 0
  • @Blechdose 程序必须有一个 ascii 值的频率数组,所有值都初始化为零才能启动:/
  • @Rex 由于 arrayq 位于 .BSS 部分,因此您需要将其内容显式归零。到目前为止,您的代码还没有这样做。

标签: arrays assembly printf character nasm


【解决方案1】:

更改.loopa标签下的代码,使其打印索引对应的字符:

    .loopa:
    mov eax, 0
    cmp [ebx+esi], eax
    je .skip
    mov eax, esi
    push ebx
    push ecx
    mov ebx, 4
    cdq
    div ebx
    push eax
    push dword acoutput
    call printf
    add esp, 8
    pop ecx
    pop ebx

【讨论】:

  • 如果目的是输出一个字符,这个除以 4 的目的是什么?
  • 因为我想输出一个字符而不是一个整数值,这是存储在频率数组中的。
  • 仔细观察发现确实需要除法,但至少简化代码并编写mov eax,esishr eax,2
猜你喜欢
  • 2019-05-24
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
相关资源
最近更新 更多