我正在 x86 架构汇编器中编写步进模式中断处理程序,但不知道如何查找并打印出
mov byte ptr [bx]
和 bx
寄存器。
到目前为止,我已经有了这个,理论上它应该可以工作,但事实并非如此。输出应如下所示:
0000:0128 C60723 mov byte ptr [bx], 23h ; bx= 0001, [bx]=12
.model small
.stack 100h
.data
senasIP dw ?
senasCS dw ?
regAX dw ?
regBX dw ?
regCX dw ?
regDX dw ?
regSP dw ?
regBP dw ?
regSI dw ?
regDI dw ?
baitas1 db ?
baitas2 db ?
baitas3 db ?
baitas4 db ?
baitas5 db ?
baitas6 db ?
zingsn_pranesimas db "Zingsninis pertraukimas: $"
mov_bx_kabl db "MOV bx, $"
bx_lygu db "bx=$"
enteris db 13,10,"$"
.code
mov ax, @data
mov ds, ax
mov ax, 0
mov es, ax ;Extra segmentas prasides ten pat kur vektoriu lentele
;To reikia, kad galetume prieiti prie vektoriu lenteles baitu reiksmiu
mov ax, es:[4]
mov bx, es:[6]
mov senasCS, bx
mov senasIP, ax ;neisikeliam tiesiai, nes nera perdavimo is atminties i atminti (butina panaudoti registrus, isimtis eilutines komandos, bet jas panaudoti butu sudetingiau)
;===================PERIMAME PERTRAUKIMA==========================
mov ax, cs
mov bx, offset pertraukimas
mov es:[4], bx
mov es:[6], ax
;=================AKTYVUOJAME ZINGSNINI REZIMA===================
pushf ;PUSH SF
pop ax
or ax, 100h ;0000 0001 0000 0000 (TF=1, kiti lieka kokie buvo)
push ax
popf ;POP SF ;>Zingsninis rezimas ijungiamas po sios komandos ivykdymo - ivykdzius kiekviena sekancia komanda ivyks zingsninis pertraukimas
;==================BELEKOKIOS KOMANDOS====================
mov byte ptr [bx],23h
mov bx,001h
;==================ISJUNGIAME ZINGSNINI REZIMA======================
pushf
pop ax
and ax, 0FEFFh ;1111 1110 1111 1111 (nuliukas priekyj F, nes skaiciai privalo prasideti skaitmeniu, ne raide) - TF=0, visi kiti liks nepakeisti
push ax
popf ;
mov ax, senasIP
mov bx, senasCS
mov es:[4], ax
mov es:[6], bx
uzdaryti_programa:
mov ah, 4Ch
int 21h
;==================================================================
;Pertraukimo apdorojimo procedura
;==================================================================
pertraukimas:
; Save register values
mov regAX, ax
mov regBX, bx
mov regCX, cx
mov regDX, dx
mov regSP, sp
mov regBP, bp
mov regSI, si
mov regDI, di
; Retrieve instruction bytes at CS:IP
pop si ; Get IP value
pop di ; Get CS value
push di ; Restore CS
push si ; Restore IP
; Copy bytes into local storage
mov al, cs:[si] ; First byte of instruction
mov ah, cs:[si+1] ; Second byte of instruction
mov baitas1, al
mov baitas2, ah
cmp al, 0C6h ; Check for opcode `C6`
jne grizti_is_pertraukimo
cmp ah, 07h ; Check for ModRM byte `07` (BX addressing mode)
jne grizti_is_pertraukimo
; Print the recognized instruction
mov ah, 9
mov dx, offset zingsn_pranesimas
int 21h
; Print CS:IP
mov ax, di
call printAX
mov ah, 2
mov dl, ":"
int 21h
mov ax, si
call printAX
call printSpace
; Print machine code bytes
mov ah, baitas1
call printAL
mov al, baitas2
call printAL
mov al, cs:[si+2] ; Immediate byte
call printAL
call printSpace
call printSpace
; Print assembly mnemonic
mov ah, 9
mov dx, offset mov_bx_kabl ; Text: `MOV byte ptr [BX],`
int 21h
mov al, cs:[si+2] ; Immediate value
call printAL
mov ah, 2
mov dl, "h" ; Append `h` for hexadecimal notation
int 21h
call printSpace
call printSpace
; Print the value of BX register before execution
mov ah, 9
mov dx, offset bx_lygu ; Text: `bx=`
int 21h
mov ax, regBX
call printAX
; Print newline
mov ah, 9
mov dx, offset enteris
int 21h
grizti_is_pertraukimo:
mov ax, regAX
mov bx, regBX
mov cx, regCX
mov dx, regDX
mov sp, regSP
mov bp, regBP
mov si, regSI
mov di, regDI
IRET ; Return from interrupt handler
;===================PAGALBINES pertraukime naudojamos proceduros================
;>>>Spausdinti AX reiksme
printAX:
push ax
mov al, ah
call printAL
pop ax
call printAL
RET
;>>>>Spausdink tarpa
printSpace:
push ax
push dx
mov ah, 2
mov dl, " "
int 21h
pop dx
pop ax
RET
;>>>Spausdinti AL reiksme
printAL:
push ax
push cx
push ax
mov cl, 4
shr al, cl
call printHexSkaitmuo
pop ax
call printHexSkaitmuo
pop cx
pop ax
RET
;>>>Spausdina hex skaitmeni pagal AL jaunesniji pusbaiti (4 jaunesnieji bitai - > AL=72, tai 0010)
printHexSkaitmuo:
push ax
push dx
and al, 0Fh ;nunulinam vyresniji pusbaiti AND al, 00001111b
cmp al, 9
jbe PrintHexSkaitmuo_0_9
jmp PrintHexSkaitmuo_A_F
PrintHexSkaitmuo_A_F:
sub al, 10 ;10-15 ===> 0-5
add al, 41h
mov dl, al
mov ah, 2; spausdiname simboli (A-F) is DL'o
int 21h
jmp PrintHexSkaitmuo_grizti
PrintHexSkaitmuo_0_9: ;0-9
mov dl, al
add dl, 30h
mov ah, 2 ;spausdiname simboli (0-9) is DL'o
int 21h
jmp printHexSkaitmuo_grizti
printHexSkaitmuo_grizti:
pop dx
pop ax
RET
END
mov ax, cs mov bx, offset pertraukimas mov es:[4], bx mov es:[6], ax
在禁用中断的情况下修改中断向量总是更好。这将避免使用不完整向量的任何风险。这就是为什么我写道:
cli
mov word [es:4], pertraukimas
mov [es:6], cs
sti
popf mov byte ptr [bx],23h mov bx,001h
一旦您的
popf
指令设置了单步标志TF,CPU将在执行以下指令后自动生成异常。需要注意的是,实际设置 TF 的指令不会生成异常。因此,在 popf
之后,不会立即调用特殊处理程序,但在执行
mov byte ptr [bx],23h
后,会出现 is。在我的程序中,我通过插入
nop
:解决了这个问题
popf ; This sets TF=1
nop
; Here happens the very first trap and CS:IP point at
mov byte [bx], 23h ; ... this instruction
mov bx, 0001h
处理器放在堆栈上的 CS:IP 值并不代表刚刚运行的指令的地址,而是代表后续指令的地址。我编写的演示程序是一个 .COM 可执行文件,其中所有段寄存器开始时都彼此相等。单步处理程序的工作原理如问题所示。我在DOSBox 0.74环境下测试过。
我得到的输出:
Zingsninis pertraukimas: 0192:012A C60723 MOV bx, 23h bx=0070
ORG 256
xor ax, ax
mov es, ax
mov ax, [es:4]
mov bx, [es:6]
mov [senasIP], ax
mov [senasCS], bx
cli
mov word [es:4], pertraukimas
mov [es:6], cs
sti
pushf : pop ax : or ax, 0100h : push ax : popf
;===============================================
nop
mov byte [bx], 23h
mov bx, 0001h
;=================================================
pushf : pop ax : and ax, 0FEFFh : push ax : popf
cli
mov ax, [senasIP]
mov [es:4], ax
mov ax, [senasCS]
mov [es:6], ax
sti
mov ax, 4C00h
int 21h
;==================================================================
;Pertraukimo apdorojimo procedura
;==================================================================
pertraukimas:
push es ax bx cx dx si di bp
mov bp, sp
les si, [bp+16]
mov ax, [es:si]
cmp ax, 07C6h ; Check for opcode `C6` and ModRM byte `07` (BX addressing mode)
jne grizti_is_pertraukimo
mov ah, 9
mov dx, zingsn_pranesimas
int 21h
mov ax, es
call printAX
mov ah, 2
mov dl, ":"
int 21h
mov ax, si
call printAX
call printSpace
mov al, 0C7h
call printAL
mov al, 07h
call printAL
mov al, [es:si+2] ; Immediate byte
call printAL
call printSpace
call printSpace
mov ah, 9
mov dx, mov_bx_kabl ; Text: `MOV byte ptr [BX],`
int 21h
mov al, [es:si+2] ; Immediate value
call printAL
mov ah, 2
mov dl, "h" ; Append `h` for hexadecimal notation
int 21h
call printSpace
call printSpace
; Print the value of BX register before execution
mov ah, 9
mov dx, bx_lygu ; Text: `bx=`
int 21h
mov ax, [bp+10] ; Pushed BX
call printAX
mov ah, 9
mov dx, enteris
int 21h
grizti_is_pertraukimo:
pop bp di si dx cx bx ax es
iret
;===================PAGALBINES pertraukime naudojamos proceduros================
printSpace:
push ax dx
mov ah, 2
mov dl, " "
int 21h
pop dx ax
ret
printAX:
push ax
mov al, ah
call printAL
pop ax
printAL:
push ax cx
push ax
mov cl, 4
shr al, cl
call printHexSkaitmuo
pop ax
call printHexSkaitmuo
pop cx ax
ret
printHexSkaitmuo:
push ax dx
and al, 15
cmp al, 10
jb .num
add al, 65-10-48
.num:
add al, 48
mov dl, al
mov ah, 2
int 21h
pop dx ax
ret
; ------------------------------------
senasIP: dw ?
senasCS: dw ?
zingsn_pranesimas: db "Zingsninis pertraukimas: $"
mov_bx_kabl: db "MOV bx, $"
bx_lygu: db "bx=$"
enteris: db 13,10,"$"
我为此使用了一个私有汇编器(类似于 FASM)。请修改 你的汇编程序可能不允许的任何内容。