【问题标题】:How does ROM_CALL work in 8086 assembly language programming?ROM_CALL 在 8086 汇编语言编程中是如何工作的?
【发布时间】:2019-05-25 06:45:21
【问题描述】:

请帮助我理解问题 1 和 2。

标记为“问题 1”的代码行是如何工作的?
当我们在“问题 2”中调用 ROM_CALL 会发生什么?

ROMRTN  DD      0FE000000H      ;Main ROM entry point.

ROM_CALL:
    PUSH    DI
    PUSH    SI
    PUSH    BP
    PUSH    DX
    PUSH    ES
    CALL    CS:DWORD PTR [ROMRTN]     ;PROBLEM 1
    POP     ES
    POP     DX
    POP     BP
    POP     SI
    POP     DI
    RET

    PAGE
    SUBTTL  Initalization code and temporary work areas.

;
; Overlayed by MSDOS by SYSINIT.
;

WRKSTK  LABEL   WORD
    DB      100 DUP (?)


HWINIT: XOR     BP,BP
    MOV     SS,BP
    MOV     SP,OFFSET WRKSTK+98     ;Some nice area for 
                                                                  ;stack

    PUSH    CS
    POP     ES

    MOV     BX,ROM_INIT
    CALL    ROM_CALL                           ;PROBLEM 2
    MOV     AH,0
    MOV     MCON,AX

    MOV     AX,SEG SYSINIT
    MOV     DS,AX

ASSUME  DS:SEG SYSINIT

    MOV     AX,CS
    ADD     AX,BIOSIZS
    MOV     DS:[CURRENT_DOS_LOCATION],AX
    MOV     DS:[MEMORY_SIZE],MAX_MEM
    MOV     AX,CS
    MOV     WORD PTR DS:[DEVICE_LIST+2],AX
    MOV     WORD PTR DS:[DEVICE_LIST],OFFSET 
    DEVSTART
    MOV     AX,CS
    ADD     AX,((OFFSET WRKSTK - OFFSET INIT)+50) /16
    MOV     DS:[FINAL_DOS_LOCATION],AX
    JMP     SYSINIT

DOSSPOT LABEL   WORD

CODE    ENDS

    END

我认为下面给出的 URL 将帮助您理解逻辑。代码快照取自完整程序的最后一个。

https://github.com/Microsoft/MS-DOS/blob/master/v2.0/source/SKELIO.ASM

【问题讨论】:

  • 看起来非常简单:对函数 (ROM_CALL) 的近调用通过内存间接 seg:off 进行远调用。有没有你在文中没有提到的更复杂的事情发生?
  • 0FE000000H 将它放在系统 BIOS 中间的某个位置。我不知道该特定入口点是否已公开记录,但鉴于您正在查看 IO.SYS,可能与初始化每个系统设备驱动程序有关。

标签: assembly x86-16


【解决方案1】:
CALL    CS:DWORD PTR [ROMRTN]     ;PROBLEM 1

问题 1 中提到的代码行是如何工作的

这条指令对存储在标签为ROMRTN的变量中的内存位置进行远调用。

ROMRTN  DD      0FE000000H      ;Main ROM entry point.

虽然您看到它显示为 32 位 dword,但您确实需要将其视为一个段:偏移对。这毕竟是 16 位代码!

ROMRTN  DD      0FE00h:0000h      ;Main ROM entry point.

或以存储在内存中的方式编写(x86 为小端):

ROMRTN  DW      0000h, 0FE00h     ;Main ROM entry point.

然后,far 调用会转到线性地址为 0FE000h 的内存位置。也就是你将段字(这里是 0FE00h)乘以 16,然后加上偏移字(这里是 0000h)。


CALL    ROM_CALL                           ;PROBLEM 2

那么当我们在问题 2 中调用 ROM_CALL 时会发生什么。

这条指令对标有 ROM_CALL 的例程进行近距离调用。
程序员可以选择内联例程的代码,但可能完整的程序会执行其中几个系统 bios 调用,因此它可以节省空间来使用这种多级方法。还可以想象,存储在 ROMRTN 中的指针会随着时间而变化,从而使该例程成为程序的灵活部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多