在 8086 实模式下比较字符串
Comparing strings in 8086 real mode
我编写了一个函数,旨在将 4 个字母的字符串与缓冲区中的前 4 个字母进行比较:
is_cmd:
; bx is the string address argument
push bx ; Push bx to stack
mov cx, [bx] ; and also move into cx
mov bx, BUFFER ; Reset BUFFER_INDEX
mov [BUFFER_INDEX], bx ; so it points to first 2 characters
mov bx, [BUFFER_INDEX]
cmp cx, [bx] ; Compare
jne is_cmd_no ; Jump if not equal
pop bx ; Retrive bx from stack
inc bx ; Move pointer to next 2 characters
mov cx, [bx] ; Move to cx
mov bx, [BUFFER_INDEX] ; Move BUFFER_INDEX into bx
inc bx ; and move to next 2 characters
cmp cx, [bx] ; Compare
jne is_cmd_no ; Jump if not equal
jmp is_cmd_yes ; Jump if equal both times
is_cmd_no:
mov ax, 1 ; Set ax to 1 so jz will not jump
ret
is_cmd_yes:
mov ax, 0 ; Set ax to 0 so jz will jump
ret
这是一个用法示例:
mov bx, REBOOT_CMD
call is_cmd
or ax, ax
jz reboot_cmd
这里是所有变量:
REBOOT_CMD:
db "rset",0
BUFFER_INDEX:
dw BUFFER
BUFFER:
times 80 db 0
BUFFER_END:
然而,当字符串不相等时,它会导致模拟器 (BOCHS) 挂起。为什么?
检查是否为命令的建议。请注意,我将“TRUE”值 1 分配给匹配项,将 FALSE
值 0 分配给非匹配结果。如果你真的喜欢另一种方式,只需在下面的代码中交换 mov ax,1
和 xor ax, ax
即可。另请注意,没有必要使用 BUFFER_INDEX
。
is_cmd:
mov cx, [bx]
mov dx, [bx+2]
lea bx, BUFFER ; Reset BUFFER_INDEX to effective address of BUFFER
; -- mov [BUFFER_INDEX], bx ; so it points to first 2 characters
; -- mov bx, [BUFFER_INDEX] ; is redundant, because BX is already equal to BUFFER_INDEX
cmp cx, [bx] ; compare first two chars
je first_two_match
jmp is_cmd_no
first_two_match:
cmp dx, [bx+2] ; compare the second two chars
jne is_cmd_no
mov ax, 1 ; is_cmd_yes
ret
is_cmd_no:
xor ax, ax
ret
用AX比较,反正改了;没有必要破坏其他任何东西;让 CPU 做 "pointer calculation",你可以从 [BX+2] 读取,不需要更改它
mov bx, REBOOT_CMD
call is_cmd
or ax, ax
jz reboot_cmd
is_cmd:
mov ax, [bx]
cmp ax, [BUFFER] ; [buffer] with [bx]
jne is_cmd_no
mov ax, [bx+2]
cmp ax, [BUFFER+2] ; [buffer+2] with [bx+2]
jne is_cmd_no
mov ax, 1 ; is_cmd_yes
ret
is_cmd_no:
xor ax, ax
ret
甚至更好,将其内联到用例中
is_reboot:
mov ax, [REBOOT_CMD]
cmp ax, [BUFFER] ; [buffer] with "rs"
jne no_reboot
mov ax, [REBOOT_CMD+2]
cmp ax, [BUFFER+2] ; [buffer+2] with "et"
jz reboot_cmd
no_reboot:
注意:2 个分支不同,第一个是 "jne",第二个 "jz" 到重启案例。它就像 C 语言中的 "AND",如果第一部分的结果为 TRUE
,则仅计算表达式的第二部分
如果你想混淆,即使 "BUFFER db "rset",0" 已经过时,你可以将 [BUFFER] 与 "rs"(即 "s" + 0x100 * "r" = 0x7372 ) 和 [BUFFER+2] 与 "et" ( = "e" + 0x100 * "t" = 0x7465 ):
is_reboot:
cmp word ptr [BUFFER],0x7372 ; [buffer] with "rs"
jne no_reboot
cmp word ptr [BUFFER+2],0x7465 ; [buffer+2] with "et"
jz reboot_cmd
no_reboot:
我编写了一个函数,旨在将 4 个字母的字符串与缓冲区中的前 4 个字母进行比较:
is_cmd:
; bx is the string address argument
push bx ; Push bx to stack
mov cx, [bx] ; and also move into cx
mov bx, BUFFER ; Reset BUFFER_INDEX
mov [BUFFER_INDEX], bx ; so it points to first 2 characters
mov bx, [BUFFER_INDEX]
cmp cx, [bx] ; Compare
jne is_cmd_no ; Jump if not equal
pop bx ; Retrive bx from stack
inc bx ; Move pointer to next 2 characters
mov cx, [bx] ; Move to cx
mov bx, [BUFFER_INDEX] ; Move BUFFER_INDEX into bx
inc bx ; and move to next 2 characters
cmp cx, [bx] ; Compare
jne is_cmd_no ; Jump if not equal
jmp is_cmd_yes ; Jump if equal both times
is_cmd_no:
mov ax, 1 ; Set ax to 1 so jz will not jump
ret
is_cmd_yes:
mov ax, 0 ; Set ax to 0 so jz will jump
ret
这是一个用法示例:
mov bx, REBOOT_CMD
call is_cmd
or ax, ax
jz reboot_cmd
这里是所有变量:
REBOOT_CMD:
db "rset",0
BUFFER_INDEX:
dw BUFFER
BUFFER:
times 80 db 0
BUFFER_END:
然而,当字符串不相等时,它会导致模拟器 (BOCHS) 挂起。为什么?
检查是否为命令的建议。请注意,我将“TRUE”值 1 分配给匹配项,将 FALSE
值 0 分配给非匹配结果。如果你真的喜欢另一种方式,只需在下面的代码中交换 mov ax,1
和 xor ax, ax
即可。另请注意,没有必要使用 BUFFER_INDEX
。
is_cmd:
mov cx, [bx]
mov dx, [bx+2]
lea bx, BUFFER ; Reset BUFFER_INDEX to effective address of BUFFER
; -- mov [BUFFER_INDEX], bx ; so it points to first 2 characters
; -- mov bx, [BUFFER_INDEX] ; is redundant, because BX is already equal to BUFFER_INDEX
cmp cx, [bx] ; compare first two chars
je first_two_match
jmp is_cmd_no
first_two_match:
cmp dx, [bx+2] ; compare the second two chars
jne is_cmd_no
mov ax, 1 ; is_cmd_yes
ret
is_cmd_no:
xor ax, ax
ret
用AX比较,反正改了;没有必要破坏其他任何东西;让 CPU 做 "pointer calculation",你可以从 [BX+2] 读取,不需要更改它
mov bx, REBOOT_CMD
call is_cmd
or ax, ax
jz reboot_cmd
is_cmd:
mov ax, [bx]
cmp ax, [BUFFER] ; [buffer] with [bx]
jne is_cmd_no
mov ax, [bx+2]
cmp ax, [BUFFER+2] ; [buffer+2] with [bx+2]
jne is_cmd_no
mov ax, 1 ; is_cmd_yes
ret
is_cmd_no:
xor ax, ax
ret
甚至更好,将其内联到用例中
is_reboot:
mov ax, [REBOOT_CMD]
cmp ax, [BUFFER] ; [buffer] with "rs"
jne no_reboot
mov ax, [REBOOT_CMD+2]
cmp ax, [BUFFER+2] ; [buffer+2] with "et"
jz reboot_cmd
no_reboot:
注意:2 个分支不同,第一个是 "jne",第二个 "jz" 到重启案例。它就像 C 语言中的 "AND",如果第一部分的结果为 TRUE
,则仅计算表达式的第二部分如果你想混淆,即使 "BUFFER db "rset",0" 已经过时,你可以将 [BUFFER] 与 "rs"(即 "s" + 0x100 * "r" = 0x7372 ) 和 [BUFFER+2] 与 "et" ( = "e" + 0x100 * "t" = 0x7465 ):
is_reboot:
cmp word ptr [BUFFER],0x7372 ; [buffer] with "rs"
jne no_reboot
cmp word ptr [BUFFER+2],0x7465 ; [buffer+2] with "et"
jz reboot_cmd
no_reboot: