zoukankan      html  css  js  c++  java
  • 【译】x86程序员手册40-10.5初始化的例子

    10.5 Initialization Example
    初始化的例子

    译注:本来想把这个例子全部注释完,但由于对intel汇编实不熟悉,有太多的伪指令,本人也是免强看懂,所以就不再做翻译了。

    $TITLE ('Initial Task')        #此处title为开始标识,$符号表示取地址
    NAME    INIT                #为一段程序命名
    init_stack  SEGMENT RW            #定义栈段 可读写 标识符为init_stack
    DW  20  DUP(?)                #保留20个双字位置
    tos         LABEL   WORD        #定义一个标号tos,类型为字
    init_stack  ENDS            #栈段init_stack定义结束 
    init_data   SEGMENT RW PUBLIC        #定义数据段 公共 可读写 标识符为init_data
    DW  20  DUP(?)                #段长度20个双字,即重复保留20个双字
    init_data   ENDS            #数据段定义结束
    init_code   SEGMENT ER PUBLIC        #代码段开始 可执行,只读,公共
    ASSUME      DS:init_data        #设定此时的数据段为上面定义的数据段
    nop
    nop
    nop
    init_start:                #入口点标识符
    ; set up stack
    mov ax, init_stack            #设置栈,将标识符init_stack放入ax
    mov ss, ax                #设置栈段寄存器
    mov esp, offset tos            #设置栈顶指针为tos的偏移,栈是高向低
    mov a1,1                #al中放1
    blink:                    #标号blink
    xor a1,1                #al清0
    out 0e4h,a1                #向0e4H端口输入al中值,此时al = 0
    mov cx,3FFFh                #cx = 3FFFh
    here:                    #标号here
    dec cx                    #cx = cx -1
    jnz here                #ZF位不等0, 则跳转到here标号处
    jmp SHORT blink                #跳到blink标号处
    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 ROM code 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
    ;
    ; 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
    ; 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
    ;
    ;   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
    ;
    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
    ; 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
    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
  • 相关阅读:
    控制层与视图层传数据
    (二)程序异常原因汇总、工具
    (十一)C语言中内存堆和栈的区别
    (二)再议MII、RMII、GMII接口
    (一)MII/MDIO接口详解
    (四)单片机系统动态内存分配,任务调度思想
    (十)Linux内核中的常用宏container_of
    (八)C语言结构体和指针
    (七)C语言中的void 和void 指针类型
    (六)C语言之typedef详解
  • 原文地址:https://www.cnblogs.com/mqmelon/p/6693660.html
Copyright © 2011-2022 走看看