2017-04-05 98 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