比较8086实模式中的字符串

时间:2016-04-02 16:20:04

标签: assembly nasm x86-16

我编写了一个函数,用于将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)挂起。为什么呢?

2 个答案:

答案 0 :(得分:1)

使用AX进行比较,无论如何都要改变;没有必要破坏别的东西;并让CPU执行"指针计算",您可以从[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",第二个a" jz"重启案例。它就像一个" AND"在C中,只计算表达式的第二部分,如果第一部分的结果为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:

答案 1 :(得分:0)

检查是否是命令的建议。注意这个事实,我指定了一个' TRUE'值为1表示匹配,FALSE值为0表示不匹配的结果。如果您真的喜欢它,请在下面的代码中交换mov ax,1xor 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