英文:
Comparing two strings only works half of the time in Assembly
问题
以下是您要翻译的代码部分:
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
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
这是您的汇编代码的关键部分,已翻译成中文。
英文:
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
答案1
得分: 2
在go_back_print_ping
函数中,应将jmp key_press
更改为jmp go_back_loop1
,以便将si
设置回reserved
。
这是在第/第三/奇数运行中reserved
内存的状态。
di si | |||||
---|---|---|---|---|---|
p | i | n | g | X | ... |
--- | --- | --- | --- | --- | ----- |
X
只是一个垃圾值,是随机值。
si
直接指向ping
的g
之后的第一个字节,即X
。
di
将不断递增,直到等于si
。在这种情况下会发生什么?嗯,我们将有一个je middle_loop1
。如果您跟随middle_loop1
的代码顺序,您会注意到在任何时候si
都没有设置回到reserved
。
因此,在第二/第四/偶数运行中,这是reserved
后内存区域的状态。
di si | |||||||||
---|---|---|---|---|---|---|---|---|---|
p | i | n | g | p | i | n | g | X | ... |
--- | --- | --- | --- | --- | --- | --- | --- | --- | ----- |
si
继续增加,将第二个ping
放在第一个ping
之后。
现在再次,di
将继续递增,但实际上我们在比较上一次写入的第一个ping
,在这种情况下,cmp byte [bx], 0
将在di
等于si
之前为真,使程序跳转到go_back_loop1
,这次将si
设置回reserved
,但它永远不会打印任何东西,并使程序陷入一个在偶数运行中一直发生错误的状态。
实际上,有多种方法可以解决这个问题,除了我建议的方法外,还存在其他问题。拿一张纸,记录所有寄存器的状态,并尝试看看发生了什么,我认为这是理解问题的最佳方法。祝你的项目好运。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论