2012-03-09 68 views
0

嗨我已经重定向划分溢出中断指向我的自定义创建的中断,在屏幕上打印'你好,我在这里',而不是打印奇怪的ASCII字符。有人能告诉我为什么吗?这里是代码奇怪的打印字符串输出从INT 0x10

[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 - 我assument认为00是除溢出的位置中断?什么是0 * 4因为任何东西乘以零意味着相同,所以为什么4?在此先感谢

回答

1

至于你怪异的性格问题,我认为:

push cs 
push es 

应该是:

push cs 
pop es 

否则:

  1. 你的push和pop是不平衡的。
  2. 您的es段寄存器未设置为es:bp以正确指向消息。它将打印es段中的偏移message处的任何内容,指向何时触发中断,而不是在实际消息所在的代码段中。
  3. 它也将最终崩溃。

对于0*4问题,我不知道。它已经有一段时间,因为我做了86,但我知道,你可以扩展间接寻址模式,比如用:

mov eax, dwarray[edx*4] 

,以确保正确的内存位置访问。在添加到dwarray基地址之前,该比例被调整为edx直到正确的值。

我不认为需要立即抵消了,所以我怀疑它是能够仅通过与相关的中断号代替0改变任何中断只是样板代码。顺便说一下,你可能不要想要改变中断向量而不确保在这个过程中禁止中断。如果之后的中断触发了,那么您已经写入了tsr的偏移量,但在之前的已经写入该段,结果将不会很漂亮。

+0

您不能使用'dx'进行间接寻址('bx','bp','si'和'di'是唯一的16位选项),除非它们是32位('edx * 2'就可以)。 – 2012-03-09 02:19:12

0

您的代码有多个问题。参见注释:

[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*42代替0*4+2