┌──────┐
│拷貝心得41集│           CPU 缺陷 ?
└──────┘
---------------------------------------------------------------------
    陳明志先生的破解與防破能力真的令在下佩服 ,底下的防破手段不知是
CPU 本身的問題 ,還是保留給防破程式 ,這是在 ESEXTER  內發現的防破手
段......。
---------------------------------------------------------------------
介紹一個不常用的指令 STOSB ,它會把 AL 放入 ES:DI
---------------------------------------------------------------------
底下我們做了一個實驗:

CODE    SEGMENT
        ASSUME  CS:CODE,DS:CODE
START   PROC    NEAR
        JMP     NEXT
MARK1   DB      'OK !',0AH,0DH,'$'
MARK2   DB      'ERROR !',0AH,0DH,'$'

NEXT :
        MOV     AX,CS
        MOV     DS,AX
        MOV     ES,AX
        STD
        MOV     DI,OFFSET RELACE+1
        MOV     AL,00H
        STOSB                           ;如果在這行單步執行一下?
RELACE :
        JMP     NO_CHANGE
        MOV     AH,09H
        MOV     DX,OFFSET MARK2
        INT     21H
        MOV     AX,4CFFH
        INT     21H
NO_CHANGE :
        MOV     AH,09H
        MOV     DX,OFFSET MARK1
        INT     21H
        MOV     AX,4CFFH
        INT     21H
START   ENDP
CODE    ENDS
        END     START

    各位不仿追蹤一下筆者這段小程式 ,您會發現如果一次執行完的話 ,
可以順利出現 OK 字樣 ,但如果單步執行的話便會出現 ERROR ,經過反覆
測試 ,終於發現問題出在 STOSB 上面 ,看起來就好像 STOSW 將 JMP 指令
改掉時 ,會停幾個指令碼的時間 ,才會去更動它 ,所以在來不及改的情況
下 ,執行到別的地方 ,很奇怪吧 ?


ps>


關於 LOCK41.DOC 所提 STOSB 指令, 並無神奇之處,
其神奇之處, 在於 80xxx 系列的 CPU , 其內部有一 "指令隊列" (instruction queue)
 其作用在於預先讀入指令, 加快 cpu 速度.
 8088 可預存 4 bytes,
 8086 可預存 6 bytes,
 80286 可預存 6 bytes,
 80386 可預存 16 bytes,

 當 CPU 執行到 STOSB 時, 原 JMP NO_CHANGE 指令已存入 "指令隊列" 中,
 故當 STOSB 要更改為 JMP CHANGE, 只更改記憶体的資料, "指令隊列" 的資料仍然不
 變, 故仍可執行 JMP NO_CHANGE.
 但 "指令隊列" 在遇到 JMP, INT, JNx, 等執行跳躍指令時, 會清除 "指令隊列" 中
 的資料, 重新讀入.
 所以當使用單步執行時, (INT 3), "指令隊列" 的資料會被清除, 而重新從記憶体讀入
 已被更改的資料(JMP CHANGE), 故.....!!!!


                                        Write by Hsieh Wen-Jinn.  12/17/93