在《orange‘s一个操作系统的实现》中书对调用门中参数复制一点一略而过,并没有对参数大小等做出解释!上网找了很久发现并没有太多这方面的描述于是自已动手实验了一下并查了80386指令手册得出如下结论:
经过实验发现:如果调用门是向32位代码段跳转时,那么调用门在用param count复制时以一个参数为双字大小进得复制,也是就要复制的参数大小为(param count)*4字节,如果调用门是向16位代码段跳转时,那么调用门在用param count复制时以一个参数为单字大小进得复制,也是就要复制的参数大小为(param count)*2字节。那么什么时候向32位代码段中跳转,什么时候向16位代码段中跳呢?这关系到门描述符中TYPE字段中的内容,如果TYPE字段的值为4则为16位门描述符用来向16位代码跳转,如果TYPE字段的值为c时则为32位门描述符,用来向32位代码段跳转!
在指令返回时本书中那副堆栈示意图旁边那段代码疑似有错误,因为RET 中的参数应与调用门中的(param count)就该是对应关系,也就是说如果是16位调用门跳转时返回时应用retf/ret (param count)*2来返回,如果是32位调用门跳转时返回时就用retf/ret (param count)*4,这样堆栈才能平衡!但那一小段代码竟用ret 3!
以下为参考资料和实验代码:
Changing Size of Call
When adding 32-bit gates to 16-bit procedures, it is important to consider
the number of parameters. The count field of the gate descriptor specifies
the size of the parameter string to copy from the current stack to the stack
of the more privileged procedure. The count field of a 16-bit gate specifies
the number of words to be copied, whereas the count field of a 32-bit gate
specifies the number of doublewords to be copied; therefore, the 16-bit
procedure must use an even number of words as parameters.
There are three ways to cause a 16-bit procedure to execute a 32-bit call:
1. Use a 16-bit call to a 32-bit interface procedure that then uses a
32-bit call to invoke the intended target.
2. Bind the 16-bit call to a 32-bit call gate.
3. Modify the 16-bit procedure, inserting an operand-size prefix before
the call, thereby changing it to a 32-bit call.
Likewise, there are three ways to cause a 32-bit procedure to execute a
16-bit call:
1.
Use a 32-bit call to a 32-bit interface procedure that then uses a
16-bit call to invoke the intended target.
2. Bind the 32-bit call to a 16-bit call gate.
3. Modify the 32-bit procedure, inserting an operand-size prefix before
the call, thereby changing it to a 16-bit call. (Be certain that the
return offset does not exceed 64K.)
Programmers can utilize any of the preceding methods to make a CALL in a
USE16 segment match the corresponding RET in a USE32 segment, or to make a
CALL in a USE32 segment match the corresponding RET in a USE16 segment.
以下为代码:
代码:;描述符类型DA_32 EQU 4000hDA_DPL0 EQU 00hDA_DPL1 EQU 20hDA_DPL2 EQU 40hDA_DPL3 EQU 60h;存储段描述符类型DA_DR EQU 90hDA_DRW EQU 92hDA_DRWA EQU 93hDA_C EQU 98hDA_CR EQU 9AhDA_CCO EQU 9ChDA_CCOR EQU 9Eh;选择子RPL的值SA_RPL0 EQU 0SA_RPL1 EQU 1SA_RPL2 EQU 2SA_RPL3 EQU 3;系统段描述符DA_LDT EQU 82hDA_386CGate EQU 8chDA_286CGate EQU 84hDA_386TSS EQU 89hDA_TaskGate EQU 85h;描述符;usage: Descriptor Base, Limit, Attr; Base: dd; Limit: dd(low 20 bits available); Addr: dw (lower 4 bits of higher byte are always 0)%macro Descriptor 3 dw %2 & 0FFFFh dw %1 & 0FFFFh db (%1 >> 16) & 0FFh dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) db (%1 >> 24) & 0FFh%endmacro ;门;usage: Gate Selector, Offset, DCount, Attr; Selector: dw; Offset dd; DCount: db; Attr: db%macro Gate 4 dw (%2 & 0FFFFh) dw %1 dw (%3 & 1Fh) | ((%4 << 8)&0FF00h) dw ((%2 >> 16) & 0FFFFh)%endmacro%include "pm.inc"org 0100h jmp LABEL_BEGIN[SECTION .GDT]LABEL_GDT: Descriptor 0, 0, 0LABEL_DESC_NORMAL Descriptor 0, 0ffffh, DA_DRWLABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_CLABEL_DESC_DATA: Descriptor 0, DataLen -1, DA_DRW LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW + DA_DPL3LABEL_DESC_TEST: Descriptor 0500000h, 0ffffh, DA_DRWLABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen-1, DA_C; + DA_32LABEL_CALL_GATE_TEST: Gate SelectorCodeDest, 0, 1, DA_286CGate+DA_DPL3LABEL_DESC_TSS: Descriptor 0, TSSLen -1, DA_386TSS + DA_DPL3LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len -1, DA_C + DA_DPL3 + DA_32LABEL_DESC_STACK3: Descriptor 0, TopOfStack3, DA_DRWA + DA_DPL3 + DA_32 GdtLen equ $ - LABEL_GDTGdtPtr dw GdtLen-1 dd 0;GDT选择子SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDTSelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDTSelectorData equ LABEL_DESC_DATA - LABEL_GDT SelectorTest equ LABEL_DESC_TEST - LABEL_GDTSelectorNormal equ LABEL_DESC_TEST - LABEL_GDTSelectorStack equ LABEL_DESC_STACK - LABEL_GDTSelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDTSelectorCodeDest equ LABEL_DESC_CODE_DEST - LABEL_GDTSelectorCallGateTest equ LABEL_CALL_GATE_TEST - LABEL_GDT + SA_RPL3SelectorCodeRing3 equ LABEL_DESC_CODE_RING3 - LABEL_GDT + SA_RPL3SelectorStack3 equ LABEL_DESC_STACK3 - LABEL_GDT + SA_RPL3SelectorTSS equ LABEL_DESC_TSS - LABEL_GDT + SA_RPL3[SECTION .data1]ALIGN 32[BITS 32]LABEL_DATA:SPValueInRealMode dw 0PMMessage db "In Protect Mode now. ^_^",0OffsetPMMessage equ PMMessage - $$StrTest: db "ABCDEFGHIJKLMNOPQRSTUVWXYZ",0OffsetStrTest equ StrTest - $$DataLen equ $ - $$[SECTION .gs]ALIGN 32[BITS 32]LABEL_STACK: times 512 db 0TopOfStack equ $ - LABEL_STACK - 1[SECTION .s3]ALIGN 32[BITS 32]LABEL_STACK3: times 512 db 0TopOfStack3 equ $ - LABEL_STACK3 -1[SECTION .tss]ALIGN 32[BITS 32]LABEL_TSS: dd 0 dd TopOfStack dd SelectorStack dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dd 0 dw 0 dw $ - LABEL_TSS + 2 DB 0ffhTSSLen equ $ - LABEL_TSS[SECTION .s16][BITS 16]LABEL_BEGIN: mov ax,cs mov ds,ax mov es,ax mov ss,ax mov sp,0100h mov [LABEL_GO_BACK_TO_REAL+3],ax mov [SPValueInRealMode],sp ;初始化32位码段描述符 xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_SEG_CODE32 mov word [LABEL_DESC_CODE32 + 2],ax shr eax,16 mov byte [LABEL_DESC_CODE32 + 4],al mov byte [LABEL_DESC_CODE32 + 7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_SEG_CODE_DEST mov word [LABEL_DESC_CODE_DEST + 2],ax shr eax,16 mov byte [LABEL_DESC_CODE_DEST + 4],al mov byte [LABEL_DESC_CODE_DEST + 7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_SEG_CODE16 mov word [LABEL_DESC_CODE16+2],ax shr eax,16 mov byte [LABEL_DESC_CODE16+4],al mov byte [LABEL_DESC_CODE16+7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_DATA mov word [LABEL_DESC_DATA+2],ax shr eax,16 mov byte [LABEL_DESC_DATA+4],al mov byte [LABEL_DESC_DATA+7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_STACK mov word [LABEL_DESC_STACK+2],ax shr eax,16 mov byte [LABEL_DESC_STACK+4],al mov byte [LABEL_DESC_STACK+7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_STACK3 mov word [LABEL_DESC_STACK3+2],ax shr eax,16 mov byte [LABEL_DESC_STACK3+4],al mov byte [LABEL_DESC_STACK3+7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_CODE_RING3 mov word [LABEL_DESC_CODE_RING3 + 2],ax shr eax,16 mov byte [LABEL_DESC_CODE_RING3 + 4],al mov byte [LABEL_DESC_CODE_RING3 + 7],ah xor eax,eax mov ax,cs shl eax,4 add eax,LABEL_TSS mov word [LABEL_DESC_TSS + 2],ax shr eax,16 mov byte [LABEL_DESC_TSS + 4],al mov byte [LABEL_DESC_TSS + 7],ah ;加载段描述符 xor eax,eax mov ax,ds shl eax,4 add eax,LABEL_GDT mov dword [GdtPtr + 2],eax ;加载GDTR lgdt [GdtPtr] ;开中断 cli ;找开A20地址线 in al,92h or al,00000010h out 92h,al ;准备切换到保护模 mov eax,cr0 or eax,1 mov cr0,eax ;进入保护模式 jmp dword SelectorCode32:0LABEL_REAL_ENTERY: mov ax,cs mov ds,ax mov es,ax mov ss,ax mov sp,[SPValueInRealMode] in al,92h and al,11111101b out 92h,al sti mov ax,4c00h int 21h[SECTION .s32][BITS 32]LABEL_SEG_CODE32:mov ax, SelectorDatamov ds, ax ; 数据段选择子mov ax, SelectorTestmov es, ax ; 测试段选择子mov ax, SelectorVideomov gs, ax ; 视频段选择子mov ax, SelectorStackmov ss, ax ; 堆栈段选择子mov esp, TopOfStack; 下面显示一个字符串 mov ah,0ch xor esi,esi xor edi,edi mov esi,OffsetPMMessage mov edi,(80 * 10 + 0) * 2 cld.1: lodsb test al,al jz .2 mov [gs:edi],ax add edi,2 jmp .1.2:; call DispReturn mov ax,SelectorTSS ltr ax push SelectorStack3 push TopOfStack push SelectorCodeRing3 push 0 retf ; mov ah,0ch ; mov al,'3' ; shl eax,16 ; push eax ; call SelectorCallGateTest:0 jmp SelectorCode16:0;-----------------------------------------------------------------------------------------DispReturn: push eax push ebx mov eax,edi mov bl,160 div bl and eax,0FFh inc eax mov bl,160 mul bl mov edi,eax pop ebx pop eax ret SegCode32Len equ $ - LABEL_SEG_CODE32[SECTION .s16code]ALIGN 32[BITS 16]LABEL_SEG_CODE16: mov ax,SelectorNormal mov ds,ax mov es,ax mov fs,ax mov gs,ax mov ss,ax mov eax,cr0 and al,11111110b mov cr0,eaxLABEL_GO_BACK_TO_REAL: jmp 0:LABEL_REAL_ENTERYCode16Len equ $ - LABEL_SEG_CODE16;以下为调用门参数调用部分[SECTION .sdest][BITS 16]LABEL_SEG_CODE_DEST: mov ax,SelectorVideo mov gs,ax mov edi,(80 * 12 + 0) * 2 mov ah,0Ch mov al,'C' ; pop eax ; pop ebx ; pop ecx ; push ecx ; push ebx ; push eax mov [gs:edi],ax; jmp $ retf 2 SegCodeDestLen equ $ - LABEL_SEG_CODE_DEST[SECTION .ring3]ALIGN 32[BITS 32]LABEL_CODE_RING3: mov ax,SelectorVideo mov gs,ax mov edi,(80 * 14 + 0) *2 mov ah,0ch mov al,'3' mov [gs:edi],ax push ax call SelectorCallGateTest:0 jmp $ ;jmp SelectorCode16:0SegCodeRing3Len equ $ - LABEL_CODE_RING3