This is the code I've so far. Everything is ready, but I think there's a logical bug here I cannot see. I have to rule out all the numbers which cannot be the one that the user picked. This ruling out continues until there's only one not-erased number in the array. However, all the numbers are eliminated from the array at the first guess cycle. I will add comments to needed parts, but code is too long and commenting everywhere would make it harder to read. Please ask me to comment the parts that you don't understand.
SYS_READ equ 3
SYS_WRITE equ 4
SYS_EXIT equ 1
STDOUT equ 1
STDIN equ 0
NEWLINE equ 10
global _start
section .data
empty_str dd '----'
counter dd 9877
number_count dd 8643
number_array times 8643 dd '0000'
number_array_end:
digit_count dd 4
msg_placed db " placed: "
msg_placed_len equ $ - msg_placed
msg_nonplaced db " nonplaced: "
msg_nonplaced_len equ $ - msg_nonplaced
msg_guess db " guess: "
msg_guess_len equ $ - msg_guess
msg_number_count db " number_count: "
msg_number_count_len equ $ - msg_number_count
section .bss
buffer resb 10
current_number resd 1
guess resd 1
placed_count resd 1
nonplaced_count resd 1
placed_count_temp resd 1
nonplaced_count_temp resd 1
number_count_temp resd 1
section .text
_start:
;--------------------------------
; filling number_array 9876->1234
;--------------------------------
mov ecx, [number_count]
mov edx, number_array
fill_number_array:
push ecx
push edx
dec dword [counter]
lea esi, [buffer]
mov eax, [counter]
call int_to_string
pop edx
mov eax, [eax]
mov [edx], eax
add edx, 4
pop ecx
loop fill_number_array
;--------------------------------
;--------------------------------
; elimination of zero and same
; digit containing numbers
;--------------------------------
mov dword [current_number], number_array
eliminate_number_array:
mov edi, [current_number]
xor ebx, ebx
eliminate_digit_outer: ; loops are named as :
mov al, [edi + ebx] ; the current operation (eliminate, guess etc.)
xor ecx, ecx ; the iterated object (digit, number)
; a descriptive word (inner/outer here, array a little above)
eliminate_digit_inner:
cmp ebx, ecx
je eliminate_digit_continue
cmp [edi + ecx], al
jne eliminate_digit_continue
call erase_number
call dec_number_count
jmp eliminate_number_next
eliminate_digit_continue:
inc ecx
cmp ecx, [digit_count]
jne eliminate_digit_inner
inc ebx
cmp ebx, [digit_count]
jne eliminate_digit_outer
eliminate_number_zeroes:
mov ecx, [digit_count]
mov al, '0'
repne scasb
jne eliminate_number_next
call erase_number
call dec_number_count
eliminate_number_next:
mov eax, [current_number]
add eax, [digit_count]
cmp eax, number_array_end
je find_number
mov [current_number], eax
jmp eliminate_number_array
;-------------------------------
;-------------------------------
; guess a number, read +-, clear
; array, repeat until found
;-------------------------------
find_number:
call make_guess
call read_placed
call read_nonplaced
mov eax, [digit_count]
cmp eax, [placed_count]
je exit
call clear_wrong_numbers
jmp find_number
;--------------------------------
exit:
mov eax, SYS_EXIT
mov ebx, 0 ; no errors
int 80h
;--------------------------------
;--------------------------------
; chosen number (by user) is
; <placed,nonplaced> far from current guess.
; so numbers which aren't <placed,nonplaced>
; away from current guess is ruled out here
;--------------------------------
clear_wrong_numbers:
push eax
push ebx
push ecx
push edx
push edi
push esi
mov dword [current_number], number_array
clear_number_array:
mov edi, [current_number]
mov esi, empty_str
mov ecx, 5
cld
repe cmpsb
jecxz clear_number_next
mov esi, [guess]
xor ebx, ebx
mov dword [nonplaced_count_temp], 0
mov dword [placed_count_temp], 0
clear_digit_outer:
mov al, [edi + ebx]
xor ecx, ecx
clear_digit_inner:
cmp [esi + ecx], al
jne clear_digit_continue
cmp ebx, ecx
je inc_placed_count_temp
inc dword [nonplaced_count_temp]
jmp clear_digit_continue
inc_placed_count_temp:
inc dword [placed_count_temp]
clear_digit_continue:
inc ecx
cmp ecx, [digit_count]
jne clear_digit_inner
inc ebx
cmp ebx, [digit_count]
jne clear_digit_outer
placed_nonplaced_match:
mov edx, [placed_count_temp]
cmp edx, [placed_count]
jne clear_number_from_array
mov edx, [nonplaced_count_temp]
cmp edx, [nonplaced_count]
jne clear_number_from_array
jmp clear_number_next
clear_number_from_array:
call erase_number
call dec_number_count
clear_number_next:
mov eax, [current_number]
add eax, [digit_count]
cmp eax, number_array_end
je clear_number_array_done
mov [current_number], eax
jmp clear_number_array
clear_number_array_done:
mov edx, msg_guess_len
mov ecx, msg_guess
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
mov edx, [digit_count]
mov ecx, [guess]
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
pop esi
pop edi
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------
;--------------------------------
; assign first appropriate number
; (!= '----') as guess
;--------------------------------
make_guess:
push eax
push ebx
push ecx
push edx
push edi
push esi
mov dword [current_number], number_array
guess_number:
mov edi, [current_number]
mov esi, empty_str
mov ecx, 5
cld
repe cmpsb
jecxz guess_empty
guess_not_empty:
mov eax, guess
mov edx, [current_number]
mov [eax], edx
jmp made_guess
guess_empty:
mov eax, [current_number]
add eax, [digit_count]
cmp eax, number_array_end
je made_guess
mov [current_number], eax
jmp guess_number
made_guess:
mov edx, msg_guess_len
mov ecx, msg_guess
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
mov edx, [digit_count]
mov ecx, [guess]
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
pop esi
pop edi
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------
;--------------------------------
; print '----' over number
;--------------------------------
erase_number:
push eax
push edx
mov eax, [current_number]
mov edx, [empty_str]
mov [eax], edx
pop edx
pop eax
ret
;--------------------------------
;--------------------------------
; print number to screen
;--------------------------------
print_number:
push eax
push ebx
push ecx
push edx
mov edx, [digit_count]
mov ecx, [current_number]
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------
;--------------------------------
; print non-erased number count
;--------------------------------
dec_number_count:
push eax
push ebx
push ecx
push edx
push esi
push edi
mov edx, msg_number_count_len
mov ecx, msg_number_count
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
dec dword [number_count]
lea esi, [buffer]
mov eax, [number_count]
call int_to_string
mov [number_count_temp], eax
mov edx, 5
mov ecx, [number_count_temp]
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------
;--------------------------------
; print newline to screen
;--------------------------------
newline:
push eax
push ebx
push ecx
push edx
push NEWLINE
mov ecx, esp
mov edx, 1
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
add esp, 4
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------
;--------------------------------
; integer-string conversion
; result's in eax
;--------------------------------
int_to_string:
add esi, 9
mov byte [esi], 10
mov ebx, 10
next_digit:
xor edx, edx
div ebx
add dl, '0'
dec esi
mov [esi], dl
test eax, eax
jnz next_digit
mov eax, esi
ret
;--------------------------------
;--------------------------------
; read placed digit count from user
;--------------------------------
read_placed:
push eax
push ebx
push ecx
push edx
mov edx, msg_placed_len
mov ecx, msg_placed
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
mov edx, 4
mov ecx, placed_count
mov ebx, STDIN
mov eax, SYS_READ
int 80h
and dword [placed_count], 0FFh
sub dword [placed_count], '0'
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------
;--------------------------------
; read nonplaced digit count from user
;--------------------------------
read_nonplaced:
push eax
push ebx
push ecx
push edx
mov edx, msg_nonplaced_len
mov ecx, msg_nonplaced
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
mov edx, 4
mov ecx, nonplaced_count
mov ebx, STDIN
mov eax, SYS_READ
int 80h
and dword [nonplaced_count], 0FFh
sub dword [nonplaced_count], '0'
pop edx
pop ecx
pop ebx
pop eax
ret
;--------------------------------