I am trying to check whether a string contains digits, this code works for test cases:
expected output : input
0 : "This is sample test!"
0 : "I've just turned five!"
1 : "My favourite number is: 1337"
0 : "Lorem ipsum dolor sit amet. This text has no numbers!"
1 : "0"
But for a reason unknown to me, it fails on all of these tests in should_work_for_more_fixed_assertions:
"I <3 NASM"
"The NASM/C environment in Codewars does not use CW-2 as its testing framework."
"Hello W0rld!"
"Hello Wor1d!"
"H2llo World!"
"H3llo World!"
"Hello4World!"
... etc.
Here is my code:
global has_digits
section .text
has_digits:
cmp rdi, 0 ; string
je end ; null pointer
xor ax, ax ; result = 0
xor cx, cx ; char = 0
xor rsi, rsi ; index = 0
dec rsi ; index--
while:
inc rsi ; index++
mov cx, [rdi+rsi] ; char = string[index]
cmp cx, 0 ; if char == 0:
je end ; break
cmp cx, 48 ; if char < '0':
jl while ; continue
cmp cx, 57 ; if char > '9':
jg while ; continue
mov ax, 1 ; result = true
end:
ret ; return
It would be great if you could tell me what I am doing wrong, without giving a full solution, but any help would be appreciated. :)
Not sure why my code is failing with specific tests
Let us turn that around and find out why 2 tests do report having found a number.
1 : "My favourite number is: 1337"
1 : "0"
When your instruction mov cx, [rdi+rsi] ; char = string[index]
supposedly retrieves a single character in the CL register, it also retrieves the following byte in the CH register. For the 2 strings that do report having found a number, it is the very last character in the string that is a digit and that effectively is followed by the zero-terminator byte, and hence processing CX instead of CL didn't pose a problem. The solution therefore is to read but a single byte from the string memory. Use the movzx ecx, byte [rdi+rsi]
instruction that zero-extends the byte into the full RCX register for maximum efficiency.
It would be great if you could tell me what I am doing wrong, without giving a full solution
It's hardly a full solution this next code snippet:
; IN (rdi) OUT (rax) MOD (rcx,rdi)
has_digits:
xor eax, eax ; RAX:= false
sub rdi, 1
jb .end ; null pointer
.while:
inc rdi ; index++
movzx ecx, byte [rdi] ; char = string[index]
test ecx, ecx ; if char == 0:
jz end ; break
sub ecx, '0'
cmp ecx, 9 ; Anything outside of [0,9] is not a digit
ja .while
inc eax ; RAX:= true, RCX=[0,9] (first digit found)
.end:
ret