2017-04-05 74 views
0

试图找到字符的字符串中的数量和不顾一切‘’空格字符忽略一个字符串空格字符ASM

我有一个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 
+1

上面的代码计算字符串中的字符数。如果你想计算不考虑空格的字符数量,那么你至少需要先尝试一下。*** Stackoverflow不是一个“为我写作业”的服务。 –

+0

我知道,对不起,如果我以“请做”类人的身份出现。我可以在正确的方向得到一个点吗?我在球场中的一般方式是什么? – Ryan

+1

提示:当你的代码反映出混淆时,清理你的'al'和'ebx'的使用和意图 –

回答

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]但从未实际使用它 - 是否应该是一个未使用的参数?

至于算法本身,你只需要保留一个单独的计数器来计算非空格字符;实际上,您可以为此保留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 
+0

我清理了一些垃圾,我不想使用测试,因为我们没有在课堂上知道。我也刚刚更新了我迄今为止用一个小函数来摆脱额外的“”角色,但它并没有摆脱它。 – Ryan

+1

我添加了关于新版本的评论;你似乎对'eax'有一些疑惑 - 'el'是'eax'的低字节,它们不是单独的寄存器,所以你不能将它用作计数器和当前字符的存储。 –

+0

好的,谢谢你澄清两个寄存器,现在有一定道理。然而,我不明白你对'inc al'的评论,以及它是如何增加错误的。现在没有人持有'[esi + ebx]'吗?另外,如果我递减ebx如我最新的编辑所示,它仍然工作?它目前并不适用于从C++端传入的一些字符串,但我不知道它是如何在逻辑上不起作用的......我猜这是行不通的,因为你的'al'语句 – Ryan

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