【问题标题】:Assembly TSR - my program crashed and I don't know the reason组装 TSR - 我的程序崩溃了,我不知道原因
【发布时间】:2012-08-22 05:12:15
【问题描述】:

我正在编写一个简单的 TSR 程序,但出现错误。

我尝试通过Int 90H 执行它,但由于某种原因它崩溃了。

我是 TSR 新手,所以问题可能很简单。

TSR:

;   Copy non-small letters

.model tiny
.code
    ORG 100H
start:
    push bp
    push si
    push cx
    push bx
;   save registers
    mov bp, sp
    sub sp, cx
    sub sp, 1 ; for $
    mov di, bp
    mov si, bx
copy:
    cmp [si], 'a'
    jl  bad
;   not small letter
    cmp [si], 'z'
    jg  bad
;   not small leter
;   good
    mov ax, [si]
    mov [bp], ax
    dec bp
bad:
    inc si
loop copy
    mov [bp-1],'$'
    mov ah, 09
    mov dx, di
    int 21H
install:
    mov al, 90H
    mov ah, 25H
    mov dx, offset start
    int 21H
finish: 
    pop bx
    pop cx
    pop si
    pop bp
;   ^ restore registers
    mov ah, 31
    int 21H
    iret
;   end
end start

主程序:

.model small
.stack 64
.data
    string  db  "Hey There"
.code
start:
    lea bx, string
    mov cx, 09
    int 90H
;   end
    mov ah, 4ch
    int 21H
end start

你知道我的程序为什么会崩溃吗?

【问题讨论】:

  • 我下周要考试,我对 TSR 一无所知.. 我 M-U-S-T 你的帮助!!
  • 等等,这是给学校的吗?寻找更好的老师(或更好的学校)。自 Windows 95 发布以来,TSR 在功能上已经过时。过去 15 多年没有人(除了你的老师?)关心它们。
  • 不.. 这是为了大学。我也真的不在乎,我没有使用 Assembly ,但此刻我必须知道这一点。我不想第二次考试不及格并再次参加这门课程。请大家 - 这对我来说真的很重要。
  • @duskwuff 显然,DOS(例如 Linux 上的 DosBox)和 Turbo C++ 仍在印度的学校中用于教授编程。
  • 这是一个学习一些 x86 汇编、中断和 TSR 的机会。

标签: assembly x86 dos tsr


【解决方案1】:

我在十多年前为 DOS 编写了一个 TSR 调试器(一种),所以我可能忘记了一些东西。

无论如何,您的中断处理程序除了cs 指向您的中断处理程序的段和ip(显然)指向您的中断代码之外,您不能假设任何其他内容,这就是您所拥有的,并且您不能修改中断处理程序中的任何其他内容(您特别想要修改的内容除外)。您必须存储您使用的所有寄存器,但您不能只将push 它们存储到堆栈中,因为您不能假设还剩下任何堆栈。所以一定要预留足够的内存来存储你在中断处理程序中修改的所有寄存器,当你保存寄存器时记得使用cs作为段寄存器,而不是默认的ds,也不是esfsgsss,因为它们都可能指向内存中的任何位置,当然不会指向为您的 TSR 保留的任何内存块。存储标志也是一个好主意。

int 21h 通常应避免在中断处理程序中调用。您可以使用 BIOS 调用 (int 10h) 或直接写入视频内存(但如果您在 TSR 中写入视频内存,请先检查视频模式)。无论如何,在 TSR 中写入显存可能会导致问题,因为您不知道当前正在运行的程序如何使用它。

如果您想确保在您自己的中断处理程序期间没有执行其他中断,您的中断处理程序开头的cli 会阻止大多数中断,恕我直言是个好主意。请记住在iret 之前允许sti 中断。

【讨论】:

    【解决方案2】:

    在我们使用 iret 指令从中断服务程序(ISR)返回之前,我们必须发送一个带有“mov al,020h”+“out 20h,al”的“中断结束”信号(EOI)到第一个可编程中断控制器(PIC 1;8259A)。

    另一种方法是跳转到旧的 ISR,而不是发送 EOI,然后返回 iret。

    ;---------------

    Ralf Browns x86/MSDOS 中断列表(RBIL)
    http://www.pobox.com/~ralf
    http://www.pobox.com/~ralf/files.html
    ftp://ftp.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/

    RBIL->inter61d.zip->PORTS.A
    ----------P0020003F--------------
    端口 0020-003F - PIC 1 - 可编程中断控制器 (8259A)
    另见:端口 00A0h-00AFh"PIC 2",INT 08"IRQ0",INT 0F"IRQ7"
    ....有关更多详细信息,请查看 RBIL..

    ;------------

    要成为 TSR,我们必须使用 INT 27h 来终止我们的应用程序的 ISR 部分保持驻留。

    RBIL->inter61c.zip->INTERRUP.K
    --------D-27---------------------
    INT 27 - DOS 1+ - 终止并继续居住
    DX = 保持常驻的字节数(最大 FFF0h)
    CS = PSP 的片段
    返回:从不
    注意:这是一个过时的调用
    INT 22、INT 23 和 INT 24 从 PSP 恢复
    不关闭任何打开的文件
    对于
    ,将保持驻留的最小字节数为 110h DOS 2.x 和 60h 用于 DOS 3.0+; DOS 1.x 没有最低要求,
    在 COMMAND.COM 而不是 DOS 内核中实现此服务
    另见:INT 21/AH=31h

    ;----------

    它认为在我们的 ISR 中使用软件中断调用不是一个好主意。 所以我更喜欢直接写入视频内存,例如在屏幕的右上角写一些数字以显示当前时间。

    ;------

    用于设置和获取中断向量:

    RBIL->inter61b.zip->INTERRUP.F
    --------D-2125-------------------
    INT 21 - DOS 1+ - 设置中断向量
    AH = 25 小时
    AL = 中断号
    DS:DX -> 新的中断处理程序
    注意:此函数优于直接修改中断
    向量表
    一些 DOS 扩展程序在此函数上放置了一个 API,因为它不是
    在保护模式下直接有意义
    在 DR DOS 5.0-6.0 下,此功能不使用任何
    DOS 内部堆栈,因此可以随时调用;但是,
    在 Novell DOS 7.0 - DR-DOS 7.02 下,此函数不可重入。
    自 1998/05/29 起,DR-DOS 7.03 不再使用任何内部堆栈和
    更早地测试此函数,以允许最小的堆栈使用
    除了 IRET 框架之外只有两个词,允许它是
    从 INT 21h 函数调用,特别是设备驱动程序。这
    修复 MCS SMB 客户端
    Novell NetWare(新的 DOS Requester 除外)监控
    的偏移量 任何 INT 24 集,如果等于启动时的值,则替换
    它自己的处理程序以允许处理网络错误;这介绍
    INT 24 处理程序偏移量的任何程序的潜在错误
    恰好与 COMMAND.COM 相同,不会有其 INT 24
    已安装处理程序
    另见:AX=2501h,AH=35h

    --------D-2135-------------------
    INT 21 - DOS 2+ - 获取中断向量
    AH = 35 小时
    AL = 中断号
    返回:ES:BX -> 当前中断处理程序
    注意:在 DR DOS 5.0+ 下,此功能不使用任何 DOS-internal
    堆栈,因此可以随时调用
    另见:AH=25h,AX=2503h

    设置中断向量的另一种方法是写入向量本身的内存位置:
    将 Timerinterrupt(8) 设置为从标签“TIMER_INT”开始的新 ISR 的示例:

    mov ax,0
    mov ds,ax
    cli
    mov WORD PTR ds:[8*4],OFFSET TIMER_INT
    mov WORD PTR ds:[8*4+2],cs
    sti
    

    德克

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 2011-11-14
      • 2013-04-09
      相关资源
      最近更新 更多