嗨,我已经重定向了除法溢出中断以指向我自定义创建的中断,该中断在屏幕上打印"你好,伙计,我在这里",而是打印奇怪的ASCII字符。有人可以告诉我为什么吗?这是代码
[ORG 100h]
jmp start
message: dw 'hello man here i am'
prntstr: push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
push cs
pop ds
mov ah, 0x13
mov al, 1
mov bh, 0
mov bl, 7
mov dx,0x0a03
mov cx,11
push cs
push es
mov bp,message
int 0x10
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
tsr: mov ah, 0
int 0x16
call prntstr
iret
;mov ah,4ch
;mov al, 6
;int 0x21
;iret
divs: mov ax,0x8569
mov dl,2
div dl
ret
start: xor ax,ax
mov es,ax
mov word[es:0*4], tsr
mov [es:0*4+2],cs
call divs
mov ax,0x4c00
int 0x21
关于代码,我还有一件事不明白,那就是我在 es:0*4 处设置偏移量的位置——我确信 00 是除法溢出中断的位置? Coz 的 0*4 是什么 乘以零意味着相同,那么为什么是 4 ? 提前致谢
至于你奇怪的性格问题,我想:
push cs
push es
应该是:
push cs
pop es
否则:
- 你的推力和爆裂声不平衡。
- 您的
es
段寄存器未设置为es:bp
正确指向消息。它将打印es
触发中断时指向的段中偏移message
的任何内容,而不是实际消息所在的代码段。 - 它最终也会崩溃。
对于0*4
问题,我不确定。自从我做 x86 以来已经有一段时间了,但我知道您可以通过以下方式扩展间接寻址模式:
mov eax, dwarray[edx*4]
以确保访问正确的内存位置。这会在添加到基址之前将edx
放大到正确的值dwarray
。
不过,我认为立即偏移不需要这样做,所以我怀疑这只是样板代码,只需将0
替换为相关的中断编号即可更改任何中断。
,您可能不希望在不确保在此过程中禁用中断的情况下更改中断向量。如果在写入偏移量 tsr
之后但在写入段之前触发中断,则结果将不漂亮。
代码中有多个问题。查看评论:
[ORG 100h]
jmp start
message: db 'hello man here i am' ; chars are 8-bit, hence db, not dw
msglen equ $ - message ; calculate message length
prntstr: push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
;push cs ; not really needed here
;pop ds
mov ah, 0x13
mov al, 1
mov bh, 0
mov bl, 7
mov dx,0x0a03
mov cx,msglen ; use proper message length
push cs
pop es ; not "push es" - copy'n'paste bug !!!
mov bp,message
int 0x10
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
tsr:
call prntstr
; skip DIV (by advancing IP) to avoid infinite loop on DIV
push bp
mov bp, sp
add word [bp+1*2], divend-divstart; IP (location of divstart) on the stack
pop bp
push ax ; save AX because int 0x16 will change it
mov ah, 0
int 0x16
pop ax ; restore AX
iret
divs: mov ax,0x8569
mov dl,2
divstart:
div dl
divend:
ret
start:
mov ax, 3
int 0x10 ; clear screen by setting mode 3
xor ax,ax
mov es,ax
cli ; update ISR address w/ ints disabled
push word[es:0*4+2] ; preserve ISR address
push word[es:0*4]
mov word[es:0*4], tsr
mov [es:0*4+2],cs
sti
call divs
cli ; update ISR address w/ ints disabled
pop word[es:0*4] ; restore ISR address
pop word[es:0*4+2]
sti
mov ax,0x4c00
int 0x21
4 是远指针大小(2 字节用于偏移量,2 字节用于段选择器(。所以,对于int 0
,中断向量表中的地址将是0*4
,对于int 1
它将是1*4
,对于int n
它将是n*4
。在这种特殊情况下,乘法是不必要的,但它不会影响代码生成,因为汇编程序将计算并替换0
0*4
和2
替换0*4+2
。