I made a program that should compare the user input and a string. It does that successfully the first time I type ping
and responds with pong
, but the second time it doesn't output anything. The third time it starts working again, and then the forth time it again stops working. What might be the problem? This is the relevant code:
key_press:
mov ah, 0x00
int 0x16
cmp al, 0x21
jge compare
jl other_chars
jmp key_press
compare:
cmp al, 0x7e
jl print
print:
pusha
mov ah, 0x0e
int 0x10
popa
mov [si], al
inc si
jmp key_press
other_chars:
cmp ah, 0x1C
je enter
cmp ah, 0x39
je space
cmp al, 0x8
je backspace
jmp key_press
enter:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
mov di, reserved
mov bx, ping_command
jmp loop1
loop1:
cmp di, si
je middle_loop1
cmp byte [bx], 0
je go_back_loop1
mov ch, [di]
cmp ch, [bx]
jne go_back_loop1
; pusha
; mov ah, 0x0e
; mov al, [di]
; int 0x10
; popa
inc di
inc bx
jmp loop1
go_back_loop1:
mov si, reserved
mov bx, ping_command
jmp key_press
middle_loop1:
mov bx, pong
pusha
jmp print_ping
print_ping:
cmp byte [bx], 0
je go_back_print_ping
mov ah, 0x0e
mov al, [bx]
int 0x10
inc bx
jmp print_ping
go_back_print_ping:
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
jmp key_press
This is the entire code:
org 0x7c00
bits 16
init:
mov ah, 0x0e
mov bx, string
mov si, reserved
jmp loop
loop:
mov al, [bx]
cmp al, 0
je key_press
int 0x10
inc bx
jmp loop
key_press:
mov ah, 0x00
int 0x16
cmp al, 0x21
jge compare
jl other_chars
jmp key_press
compare:
cmp al, 0x7e
jl print
print:
pusha
mov ah, 0x0e
int 0x10
popa
mov [si], al
inc si
jmp key_press
other_chars:
cmp ah, 0x1C
je enter
cmp ah, 0x39
je space
cmp al, 0x8
je backspace
jmp key_press
enter:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
mov di, reserved
mov bx, ping_command
jmp loop1
loop1:
cmp di, si
je middle_loop1
cmp byte [bx], 0
je go_back_loop1
mov ch, [di]
cmp ch, [bx]
jne go_back_loop1
; pusha
; mov ah, 0x0e
; mov al, [di]
; int 0x10
; popa
inc di
inc bx
jmp loop1
go_back_loop1:
mov si, reserved
mov bx, ping_command
jmp key_press
middle_loop1:
mov bx, pong
pusha
jmp print_ping
print_ping:
cmp byte [bx], 0
je go_back_print_ping
mov ah, 0x0e
mov al, [bx]
int 0x10
inc bx
jmp print_ping
go_back_print_ping:
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
jmp key_press
space:
pusha
mov ah, 0x0e
mov al, ' '
int 0x10
popa
mov byte [si], ' '
inc si
jmp key_press
backspace:
pusha
mov ah, 0x0e
int 0x10
mov al, ' '
int 0x10
mov al, 0x8
int 0x10
popa
dec si
jmp key_press
halt:
hlt
jmp halt
reserved resb 256
ping_command db "ping", 0
pong db "pong", 0
string db "Hello, World!", 0
times 510-($-$$) db 0
dw 0xAA55
In the function go_back_print_ping
, jmp key_press
should be changed to jmp go_back_loop1
, so that it would set si
back to reserved
.
This is the memory at `reserved` in the first/third/odd runs.
di si
|---|---|---|---|---|-----
| p | i | n | g | X | ...
|---|---|---|---|---|-----
X
is just a garbage value, whatever happened to be there.
si
points directly to the first byte after the 'g' of 'ping', which is X
.
di
will keep incrementing until it is equal to si
. What would happen in that case? Well, we would have a je middle_loop1
. If you follow the code sequence of middle_loop1
, you'll notice that at no point in time is si
set back to reserved
.
So in the second/fourth/even runs, this is the state of the memory region after reserved
di si
|---|---|---|---|---|---|---|---|---|-----
| p | i | n | g | p | i | n | g | X | ...
|---|---|---|---|---|---|---|---|---|-----
si
kept on incrementing, putting the second ping
we write after the first one.
Now again, di
will keep incrementing, BUT we are in fact comparing the first ping, that was written the previous time, in this case, cmp byte [bx], 0
will be true before di
is equal to si
, making the program jump to go_back_loop1
this time setting si
back to reserved
BUT it never prints anything, and putting the program in a state where the bug will keep on happening in even runs.
There are actually multiple ways this could be solved, other than what I suggested, there are also other problems. It's a really fun exercise to take a piece of paper and have the state of all registers and try to see what happens when, I think it's the best way to understand the problem. Good luck with your project.