2016-04-02 64 views
0

:ここ比較文字列

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 
文字列は、それはエミュレータ(Bの原因と等しくない場合しかし、

REBOOT_CMD: 
    db "rset",0 

BUFFER_INDEX: 
    dw BUFFER 

BUFFER: 
    times 80 db 0 
BUFFER_END: 

そして、ここではすべての変数ですOCHS)をハングアップします。どうして?

+0

あなたのプッシュとポップを見てください。比較の後、あなたはプッシュしたがポップしなかった。 (無関係) 'inc bx'は次の2文字セットを指しません。ここで 'add bx、2'が必要です。 – usr2564301

+0

[buffer_index]を使う必要はありません。単に[bx]と[buffer]と[bx + 2]を[buffer + 2]と比較するのはなぜですか? – Tommylee2k

答えて

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」、もう1つは再起動の場合は「jz」です。それは、 "BUFFER db" rset "、0"であってもobfusctingしたいと思えば、最初の結果がTRUEの場合は、式の2番目の部分だけが評価される "AND"のようになります。

(BUFFER)と "et"(= "e" + 0x100 * "t" = 0x7465)の "rs"( "s" + "0x100 *" r "= 0x7372)と[BUFFER + 2]を比較することができます):

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: 
+0

ありがとう、これは完全に働いた! –

+0

レジスタの内容に基づいてフラグを設定するための慣用句として、「またはax、ax」を使用しないでください(別名ゼロと比較)。 'test ax、ax'には、デコードするブランチとのマクロ融合やより速く実行することを含むいくつかの重要な利点があります。 @エドワードアトキンソン:この回答があなたの問題を解決した場合は、上下の投票ボタンの下にあるチェックマークをクリックして、それを受け入れることを忘れないようにしてください。 –

+0

また、一部のアセンブラ (NASMとMASMを含む)では、 'cmp ...、 'rs''と' cmp ...'などと書くことができるので、それほど難読化されていません。文字列を即時データとして保存するのはいい考えです。 –

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