请帮助我理解问题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
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中的指针会随着时间的推移而变化,使该例程成为程序中灵活的一部分。