比较两个字符串在汇编中只有一半的时间有效。

huangapple go评论56阅读模式
英文:

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直接指向pingg之后的第一个字节,即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.

huangapple
  • 本文由 发表于 2023年2月27日 18:07:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75579087.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定