如何用TSS进行任务切换?我切换不成功:((内有汇编代码/as86)‹‹12

导读:
  十分感谢mik的帮助。问题找到了。
  LDT为系统段,我把它设为数据段,结果不行了。
  Intel手册中没说,我以为两个都行的都行的。
  ————————————————————————————————————————————
  我的VM乱报错
  
  ,以后我可不相信它了。
  
  结果让我绕了好大弯子,什么ss段出错,什么ds段不对。
  我吐血。发了我好多精力啊。
  --------------------------------------------------------------------------------------------------------
  PS:看了intel的sample,我才明白什么才叫assembler。那叫什么乱七八糟的代码。是人看的么??又是cp,又是builer分配的。我手上没有masm,也没有dos,分析目标代码都不行。
  附上:intel的代码
  [Copy to clipboard][-] CODE:
  10.4.5 First Task
  The initialization procedure can run awhile in protected mode without
  initializing the task register; however, before the first task switch, the
  following conditions must prevail:
  ● There must be a valid task state segment (TSS) for the new task. The
  stack pointers in the TSS for privilege levels numerically less than or
  equal to the initial CPL must point to valid stack segments.
  ● The task register must point to an area in which to save the current
  task state. After the first task switch, the information dumped in this
  area is not needed, and the area can be used for other purposes.
  10.5 Initialization Example
  $TITLE ('Initial Task')
  NAME INIT
  init_stack SEGMENT RW
  DW 20 DUP(?)
  tos LABEL WORD
  init_stack ENDS
  init_data SEGMENT RW PUBLIC
  DW 20 DUP(?)
  init_data ENDS
  init_code SEGMENT ER PUBLIC
  ASSUME DS:init_data
  nop
  nop
  nop
  init_start:
  set up stack
  mov ax, init_stack
  mov ss, ax
  mov esp, offset tos
  mov a1,1
  blink:
  xor a1,1
  out 0e4h,a1
  mov cx,3FFFh
  here:
  dec cx
  jnz here
  jmp SHORT blink
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 179 of 421
  hlt
  init_code ends
  END init_start, SS:init_stack, DS:init_data
  $TITLE('Protected Mode Transition -- 386 initialization')
  NAME RESET
  *****************************************************************
  Upon reset the 386 starts executing at address 0FFFFFFF0H. The
  upper 12 address bits remain high until a FAR call or jump is
  executed.
  Assume the following:
  - a short jump at address 0FFFFFFF0H (placed there by the
  system builder) causes execution to begin at START in segment
  RESET_CODE.
  - segment RESET_CODE is based at physical address 0FFFF0000H,
  i.e. at the start of the last 64K in the 4G address space.
  Note that this is the base of the CS register at reset. If
  you locate ROMcode above this address, you will need to
  figure out an adjustment factor to address things within this
  segment.
  *****************************************************************
  $EJECT ;
  Define addresses to locate GDT and IDT in RAM.
  These addresses are also used in the BLD386 file that defines
  the GDT and IDT. If you change these addresses, make sure you
  change the base addresses specified in the build file.
  GDTbase EQU 00001000H ;physical address for GDT base
  IDTbase EQU 00000400H ;physical address for IDT base
  PUBLIC GDT_EPROM
  PUBLIC IDT_EPROM
  PUBLIC START
  DUMMY segment rw ;ONLY for ASM386 main module stack init
  DW 0
  DUMMY ends
  *****************************************************************
  Note: RESET CODE must be USEl6 because the 386 initally executes
  in real mode.
  RESET_CODE segment er PUBLIC USE16
  ASSUME DS:nothing, ES:nothing
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 180 of 421
  386 Descriptor template
  DESC STRUC
  lim_0_15 DW 0 ;limit bits (0..15)
  bas_0_15 DW 0 ;base bits (0..15)
  bas_16_23 DB 0 ;base bits (16..23)
  access DB 0 ;access byte
  gran DB 0 ;granularity byte
  bas_24_31 DB 0 ;base bits (24..31)
  DESC ENDS
  The following is the layout of the real GDT created by BLD386.
  It is located in EPROM and will be copied to RAM.
  GDT[O] ... NULL
  GDT[1] ... Alias for RAM GDT
  GDT[2] ... Alias for RAM IDT
  GDT[2] ... initial task TSS
  GDT[3] ... initial task TSS alias
  GDT[4] ... initial task LDT
  GDT[5] ... initial task LDT alias
  define entries in GDT and IDT.
  GDT_ENTRIES EQU 8
  IDT_ENTRIES EQU 32
  define some constants to index into the real GDT
  GDT_ALIAS EQU 1*SIZE DESC
  IDT_ALIAS EQU 2*SIZE DESC
  INIT_TSS EQU 3*SIZE DESC
  INIT_TSS_A EQU 4*SIZE DESC
  INIT_LDT EQU 5*SIZE DESC
  INIT_LDT_A EQU 6*SIZE DESC
  location of alias in INIT_LDT
  INIT_LDT_ALIAS EQU 1*SIZE DESC
  access rights byte for DATA and TSS descriptors
  DS_ACCESS EQU 010010010B
  TSS_ACCESS EQU 010001001B
  This temporary GDT will be used to set up the real GDT in RAM.
  Temp_GDT LABEL BYTE ;tag for begin of scratch GDT
  NULL_DES DESC <>;NULL descriptor
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 181 of 421
  32-Gigabyte data segment based at 0
  FLAT_DES DESC <0FFFFH,0,0,92h,0CFh,0>
  GDT_eprom DP ? ;Builder places GDT address and limit
  in this 6 byte area.
  IDT_eprom DP ? ;Builder places IDT address and limit
  in this 6 byte area.
  Prepare operand for loadings GDTR and LDTR.
  TGDT_pword LABEL PWORD ;for temp GDT
  DW end_Temp_GDT_Temp_GDT -1
  DD 0
  GDT_pword LABEL PWORD ;for GDT in RAM
  DW GDT_ENTRIES * SIZE DESC -1
  DD GDTbase
  IDT_pword LABEL PWORD ;for IDT in RAM
  DW IDT_ENTRIES * SIZE DESC -1
  DD IDTbase
  end_Temp_GDT LABEL BYTE
  Define equates for addressing convenience.
  GDT_DES_FLAT EQU DS:GDT_ALIAS +GDTbase
  IDT_DES_FLAT EQU DS:IDT_ALIAS +GDTbase
  INIT_TSS_A_OFFSET EQU DS:INIT_TSS_A
  INIT_TSS_OFFSET EQU DS:INIT_TSS
  INIT_LDT_A_OFFSET EQU DS:INIT_LDT_A
  INIT_LDT_OFFSET EQU DS:INIT_LDT
  define pointer for first task switch
  ENTRY POINTER LABEL DWORD
  DW 0, INIT_TSS
  ******************************************************************
  Jump from reset vector to here.
  START:
  CLI ;disable interrupts
  CLD ;clear direction flag
  LIDT NULL_des ;force shutdown on errors
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 182 of 421
  move scratch GDT to RAM at physical 0
  XOR DI,DI
  MOV ES,DI ;point ES:DI to physical location 0
  MOV SI,OFFSET Temp_GDT
  MOV CX,end_Temp_GDT-Temp_GDT ;set byte count
  INC CX
  move table
  REP MOVS BYTE PTR ES:[DI],BYTE PTR CS:[SI]
  LGDT tGDT_pword ;load GDTR for Temp. GDT
  (located at 0)
  switch to protected mode
  MOV EAX,CR0 ;get current CRO
  MOV EAX,1 ;set PE bit
  MOV CRO,EAX ;begin protected mode
  clear prefetch queue
  JMP SHORT flush
  flush:
  set DS,ES,SS to address flat linear space (0 ... 4GB)
  MOV BX,FLAT_DES-Temp_GDT
  MOV US,BX
  MOV ES,BX
  MOV SS,BX
  initialize stack pointer to some (arbitrary) RAM location
  MOV ESP, OFFSET end_Temp_GDT
  copy eprom GDT to RAM
  MOV ESI,DWORD PTR GDT_eprom +2 ;get base of eprom GDT
  (put here by builder).
  MOV EDI,GDTbase ;point ES:EDI to GDT base in RAM.
  MOV CX,WORD PTR gdt_eprom +0 ;limit of eprom GDT
  INC CX
  SHR CX,1 ;easier to move words
  CLD
  REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
  copy eprom IDT to RAM
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 183 of 421
  MOV ESI,DWORD PTR IDT_eprom +2 ;get base of eprom IDT
  (put here by builder)
  MOV EDI,IDTbase ;point ES:EDI to IDT base in RAM.
  MOV CX,WORD PTR idt_eprom +0 ;limit of eprom IDT
  INC CX
  SHR CX,1
  CLD
  REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
  switch to RAM GDT and IDT
  LIDT IDT_pword
  LGDT GDT_pword
  MOV BX,GDT_ALIAS ;point DS to GDT alias
  MOV DS,BX
  copy eprom TSS to RAM
  MOV BX,INIT_TSS_A ;INIT TSS A descriptor base
  has RAM location of INIT TSS.
  MOV ES,BX ;ES points to TSS in RAM
  MOV BX,INIT_TSS ;get inital task selector
  LAR DX,BX ;save access byte
  MOV [BX].access,DS_ACCESS ;set access as data segment
  MOV FS,BX ;FS points to eprom TSS
  XOR si,si ;FS:si points to eprom TSS
  XOR di,di ;ES:di points to RAM TSS
  MOV CX,[BX].lim_0_15 ;get count to move
  INC CX
  move INIT_TSS to RAM.
  REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si]
  MOV [BX].access,DH ;restore access byte
  change base of INIT TSS descriptor to point to RAM.
  MOV AX,INIT_TSS_A_OFFSET.bas_0_15
  MOV INIT_TSS_OFFSET.bas_0_15,AX
  MOV AL,INIT_TSS_A_OFFSET.bas_16_23
  MOV INIT_TSS_OFFSET.bas_16_23,AL
  MOV AL,INIT_TSS_A_OFFSET.bas_24_31
  MOV INIT_TSS_OFFSET.bas_24_31,AL
  change INIT TSS A to form a save area for TSS on first task
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 184 of 421
  switch. Use RAM at location 0.
  MOV BX,INIT_TSS_A
  MOV WORD PTR [BX].bas_0_15,0
  MOV [BX].bas_16_23,0
  MOV [BX].bas_24_31,0
  MOV [BX].access,TSS_ACCESS
  MOV [BX].gran,O
  LTR BX ;defines save area for TSS
  copy eprom LDT to RAM
  MOV BX,INIT_LDT_A ;INIT_LDT_A descriptor has
  base address in RAM for INIT_LDT.
  MOV ES,BX ;ES points LDT location in RAM.
  MOV AH,[BX].bas_24_31
  MOV AL,[BX].bas_16_23
  SHL EAX,16
  MOV AX,[BX].bas_0_15 ;save INIT_LDT base (ram) in EAX
  MOV BX,INIT_LDT ;get inital LDT selector
  LAR DX,BX ;save access rights
  MOV [BX].access,DS_ACCESS ;set access as data segment
  MOV FS,BX ;FS points to eprom LDT
  XOR si,si ;FS:SI points to eprom LDT
  XOR di,di ;ES:DI points to RAM LDT
  MOV CX,[BX].lim_0_15 ;get count to move
  INC CX
  move initial LDT to RAM
  REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si]
  MOV [BX].access,DH ;restore access rights in
  INIT_LDT descriptor
  change base of alias (of INIT_LDT) to point to location in RAM.
  MOV ES:[INIT_LDT_ALIAS].bas_0_15,AX
  SHR EAX,16
  MOV ES:[INIT_LDT_ALIAS].bas_16_23,AL
  MOV ES:[INIT_LDT_ALIAS].bas_24_31,AH
  now set the base value in INIT_LDT descriptor
  MOV AX,INIT_LDT_A_OFFSET.bas_0_15
  MOV INIT_LDT_OFFSET.bas_0_15,AX
  MOV AL,INIT_LDT_A_OFFSET.bas_16_23
  MOV INIT_LDT_OFFSET.bas_16_23,AL
  MOV AL,INIT_LDT_A_OFFSET.bas_24_31
  INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
  Page 185 of 421
  MOV INIT_LDT_OFFSET.bas_24_31,AL
  Now GDT, IDT, initial TSS and initial LDT are all set up.
  Start the first task!
  '
  JMP ENTRY_POINTER
  RESET_CODE ends
  END START, SS:DUMMY,DS:DUMMY

本文转自
http://linux.chinaunix.net/bbs/viewthread.php?tid=907431&page=2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值