请帮助我理解问题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
答案 0 :(得分:2)
CALL CS:DWORD PTR [ROMRTN] ;PROBLEM 1
问题1中提到的代码行如何工作
此指令对内存位置进行了远距离调用,其地址存储在标有 ROMRTN 的变量中。
ROMRTN DD 0FE000000H ;Main ROM entry point.
尽管您看到的是显示为32位双字,但实际上您需要将其视为一个段:偏移对。毕竟这是16位代码!
ROMRTN DD 0FE00h:0000h ;Main ROM entry point.
或写成将其存储在内存中的方式(x86为小端):
ROMRTN DW 0000h, 0FE00h ;Main ROM entry point.
然后,远端调用转到线性地址为0FE000h的存储位置。也就是说,您将段字(这里是0FE00h)乘以16,然后加上偏移字(这里是0000h)。
CALL ROM_CALL ;PROBLEM 2
然后,当我们在问题2处调用ROM_CALL时会发生什么。
该指令对标有 ROM_CALL 的例程进行了近距离调用。
程序员可能已经选择内联例程的代码,但是完整的程序可能执行了其中的一些系统BIOS调用,因此节省了采用这种多级方法的空间。还可以想象,存储在 ROMRTN 中的指针会随时间变化,从而使该例程成为程序的灵活部分。