尝试查找字符串中的字符数并忽略所有" "空格字符
我有一个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
答案 0 :(得分:0)
你做了很多无用的事情而没有做任何事情来忽略空间。
你真的不需要设置一个新的堆栈帧,对于这样一个简单的例程,你可以在破坏的寄存器中做所有事情,或者最多在堆栈中保存一些寄存器;
inc al
毫无意义 - 您正在递增字符值,只是在下一次循环迭代时将其丢弃。
push fmt
然后立即清理堆栈?它有什么意义?
mov ebx, 0
- 没有人这样做,将寄存器归零的惯用方法是xor ebx,ebx
(指令编码更紧凑);
cmp al, 0
鉴于你只对平等感兴趣,你可以做test al, al
(更紧凑);
你读过[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
将成为返回值,并且您可以自由地ecx
和edx
,所以:
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