无视字符串' ASM中的空格字符

时间:2017-04-05 05:23:30

标签: string assembly

尝试查找字符串中的字符数并忽略所有" "空格字符

我有一个C ++部分将字符串传递给asm,这是我的asm 工作正常,唯一的问题是空间字符也被计算在内。

stringLength PROC PUBLIC
    PUSH    ebp             ; save caller base pointer
    MOV     ebp, esp        ; set our base pointer
    SUB     esp, (1 * 4)    ; allocate uint32_t local vars
    PUSH    edi
    PUSH    esi
    ; end prologue


    MOV esi, [ebp+8]            ;gets the string
    xor ebx, ebx

COMPARE:
    MOV al, [esi + ebx]     
    CMP al, 0               ;compare character of string with 0
    JE FINALE               ;if = to 0 go to end
    INC ebx                 ;counter
    CMP al, ' '             ;compare with sapce
    JE SPACE                ;go get rid of the space and keep going
    INC al                  ;otherwise inc al to next character and repeat
    JMP COMPARE             

SPACE:
    DEC ebx                 ;get rid of the extra space
    INC al
    JMP COMPARE             ;goes back to compare


FINALE:

    MOV eax,ebx         ; bring back the counter
    ADD esp, (2 * 4)    ; clear the stack
    POP esi 
    POP edi
    MOV esp, ebp        ; deallocate locals
    POP ebp             ; restore caller base pointer
RET

stringLength ENDP   ; end the procedure
END stringLength

2 个答案:

答案 0 :(得分:0)

你做了很多无用的事情而没有做任何事情来忽略空间。

  1. 你真的不需要设置一个新的堆栈帧,对于这样一个简单的例程,你可以在破坏的寄存器中做所有事情,或者最多在堆栈中保存一些寄存器;

  2. inc al毫无意义 - 您正在递增字符值,只是在下一次循环迭代时将其丢弃。

  3. push fmt然后立即清理堆栈?它有什么意义?

  4. mov ebx, 0 - 没有人这样做,将寄存器归零的惯用方法是xor ebx,ebx(指令编码更紧凑);

  5. cmp al, 0鉴于你只对平等感兴趣,你可以做test al, al(更紧凑);

  6. 你读过[ebp + 12]但从未真正使用它 - 那应该是一个未使用的参数吗?

  7. 至于算法本身,你只需要保留一个单独的计数器来计算非空格字符;实际上,您可以保留ebx,并直接递增esi以迭代字符。例如:

        xor ebx, ebx
    COMPARE:
        mov al, [esi] 
        cmp al, ' ' 
        jne nonspace
        inc ebx
    nonspace:
        test al, al
        jz FINALE 
        inc esi
        jmp COMPARE 
    FINALE:
    

    现在,这可以进一步简化,eax将成为返回值,并且您可以自由地ecxedx,所以:

    stringLength PROC PUBLIC
        mov ecx,[esp+4]         ; get the string
        xor eax,eax             ; zero the counter
    compare:
        mov dl,[ecx]            ; read character
        cmp dl,' '
        jne nospace
        inc eax                 ; increase counter if it's a space
    nospace:
        test dl,dl
        jz end                  ; go to end if we reached the NUL
        inc ecx                 ; next character
        jmp compare
    end:
        ret                     ; straight return, nothing else to do
    stringLength ENDP   ; end the procedure
    

    编辑:关于更新版本

    COMPARE:
        MOV al, [esi + ebx]     
        CMP al, 0
        JE FINALE
        INC ebx
        CMP al, " "     ; I don't know what assembler you are using,
                        ; but typically character values are in single quotes
        JE SPACE
        INC al          ; this makes no sense! you are incrementing
                        ; the _character value_, not the position!
                        ; it's going to be overwritten at the next iteration
        JMP COMPARE             
    
    SPACE:
        INC eax         ; you cannot use eax as a counter, you are already
                        ; using it (al) as temporary store for the current
                        ; character!
        JMP COMPARE
    

答案 1 :(得分:0)

我认为我们需要使用整个eax寄存器来比较值。以这种方式:

; inlet data:
; eax - pointer to first byte of string
; edx - count of bytes in string
; ecx - result (number of non-space chars)
              push esi
              mov ecx, 0
              mov esi, eax
@@compare:    cmp edx, 4
              jl @@finalpass
              mov eax, [esi]
              xor eax, 20202020h  ; 20h - space char
              cmp al, 0
              jz @@nextbyte0
              inc ecx
@@nextbyte0:  cmp ah, 0
              jz @@nextbyte1
              inc ecx
@@nextbyte1:  shr eax, 16
              cmp al, 0
              jz @@nextbyte2
              inc ecx
@@nextbyte2:  cmp ah, 0
              jz @@nextbyte3
              inc ecx
@@nextbyte3:  add esi, 4
              sub edx, 4
              jmp @@compare
@@finalpass:  and edx, edx
              jz @@fine
              mov al, [esi]
              cmp al, 20h
              jz  @@nextbyte4
              inc ecx
@@nextbyte4:  inc esi
              dec edx
              jmp @@finalpass
@@fine:       pop esi
; save the result data and restore stack