【问题标题】:Comparing strings in 8086 real mode在 8086 实模式下比较字符串
【发布时间】:2016-04-02 16:20:04
【问题描述】:

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

【问题讨论】:

  • 看看你的推送和弹出。比较后,你推但没有弹出。 (无关)inc bx 没有使其指向下一组 2 个字符。你需要add bx, 2这里。
  • 没有必要使用[buffer_index],为什么不简单地将[bx]与[Buffer]和[bx+2]与[buffer+2]进行比较?

标签: assembly nasm x86-16


【解决方案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:

注意:两个分支不同,第一个是“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:

【讨论】:

  • 不要使用or ax, ax 作为根据寄存器内容设置标志的习惯用法(也就是与零比较)。 test ax,ax 具有一些显着优势,包括宏融合与分支以更快地解码和运行。 @EdwardAtkinson:如果此答案解决了您的问题,请不要忘记单击上/下投票按钮下的复选标记以将其标记为已接受。
  • 另外,在某些汇编程序(包括 NASM 和 MASM)中,您可以编写 cmp ..., 'rs'cmp ..., 'et',所以它并没有那么混淆。将字符串存储为即时数据的好主意。
【解决方案2】:

检查它是否是命令的建议。请注意,我将 1 的“TRUE”值分配给匹配项,将 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 2018-01-16
    • 1970-01-01
    • 2022-12-05
    相关资源
    最近更新 更多