系统的简单注解

来源:互联网 发布:网络约车平台架构图 编辑:程序博客网 时间:2024/06/16 13:50


该文件包括了系统进程的创建、用户进程的安装、进程控制块链表的控制(运行链表、休眠链表)、进程窗口的绘制、硬盘扇区的读取。

 

Set_TSS_sel:安装TSS段;

Set_LDT_sel:安装LDT段;

Load_core_task:创建系统进程(权限0);

Load_usr_task:创建用户进程(权限3);

mount_task_running_que:将进程结构安装到运行队列中;

mount_task_run_to_pend_que:将进程结构从运行队列放入暂停队列;

mount_task_pend_to_run_que:将进程结构从暂停队列放入运行队列;

switch_task2:轮转切换当前执行的进程;

wakeup_task:检查进程休眠时间是否到时,并唤醒;

draw_task_window:绘制用户进程窗口;

read_hard_disk_0:从硬盘读取一个逻辑扇区;

 

代码中的SYS_PROCUSR1_PROCUSR2_PROC分别保存了系统进程、用户进程1、用户进程2的控制块。


;===============================================================================
;=== 本程序包括了进程管理的主要功能:                                        ===
;=== 1.进程结构初始化                                                        ===
;=== 2.进程的安装、启动、唤醒、睡眠                                          ===
;===============================================================================


;-------------------------------------------------------------------------------
Set_TSS_sel:                              ;安装TSS段
                                          ;输入参数: eax-—TSS段基地址
                                          ;输出参数: cx—-gdt中的选择子
 
     push edx                              ;保存edx


     xor ecx, ecx                          ;ecx清零
     sgdt [pgdt]                           ;获取gdt表长度和基址
     mov cx, word [pgdt]                   ;段界限
     mov edx, dword [pgdt+2]               ;段基址
     inc cx                                ;gdt表长度
     add edx, ecx                          ;安装地址       
     mov word [edx], 103                   ;TSS段长度的低16位
     mov word [edx+2], ax                  ;TSS段基址的低16位
     shr eax, 16                           ;TSS段基址右移16位
     mov byte [edx+4], al                  ;TSS段基址的中8位
     mov byte [edx+7], ah                  ;TSS段基址的高8位
     mov byte [edx+5], 1_00_0_1001B        ;P-1,TYPE-9(可用386TSS段)
     mov byte [edx+6], 0_1_0_0_0000B       ;G-0,X-1,limit-0
     add word [pgdt], 8                    ;gdt表长度增加8字节
     lgdt [pgdt]                           ;重新安装gdt表到系统

     pop edx                               ;弹出edx

  ret

;-------------------------------------------------------------------------------
Set_LDT_sel:                               ;安装LDT段
                                           ;输入参数: eax-—LDT段基地址
                                           ;输出参数: cx—-gdt中的选择子
 
     push edx                              ;保存edx

     xor ecx, ecx                          ;ecx清零
     sgdt [pgdt]                           ;获取gdt表长度和基址
     mov cx, word [pgdt]                   ;段界限
     mov edx, dword [pgdt+2]               ;段基址
     inc cx                                ;gdt表长度
     add edx, ecx                          ;安装地址       
     mov word [edx], 15                    ;LDT段长度的低16位
     mov word [edx+2], ax                  ;LDT段基址的低16位
     shr eax, 16                           ;LDT段基址右移16位
     mov byte [edx+4], al                  ;LDT段基址的中8位
     mov byte [edx+7], ah                  ;LDT段基址的高8位
     mov byte [edx+5], 1_11_0_0010B        ;P-1,DPL=3,TYPE-2(LDT段)
     mov byte [edx+6], 0_1_0_0_0000B       ;G-0,X-1,limit-0
     add word [pgdt], 8                    ;gdt表长度增加8字节
     lgdt [pgdt]                           ;重新安装gdt表到系统

     pop edx                               ;弹出edx

     ret

;-------------------------------------------------------------------------------
Load_core_task:                           ;创建系统进程(权限0)
 
     pushad
 
     ;内核任务的TSS段填写,清空缓冲区,使段内所有保留位置0
     mov eax, SYS_PROC + proc_ctrl.tss
     mov ecx, 104
_init_tss:
     mov byte [eax], 0x0
     inc eax
     loop _init_tss
 
     mov eax, SYS_PROC + proc_ctrl.tss
     mov ecx, cr3
     mov dword [eax + 0x1c], ecx        ;此处的CR3的写入必须要有,因为Set_TSS_sel不会主动加入页目录!!!
 
     ;在gdt中写入tss段描述符
     call Set_TSS_sel                   ;安装TSS,段首地址在eax中
     mov [SYS_PROC + proc_ctrl.task_sel], cx
     ltr cx                             ;将内核任务写入系统
 
     mov eax, SYS_PROC
     mov [SYS_PROC + proc_ctrl.pre_task], eax   ;系统进程的前一进程指向自己
     mov [SYS_PROC + proc_ctrl.next_task], eax ;系统进程的后一进程也指向自己
 
     ;记录当前工作进程
     mov eax, SYS_PROC
     mov [_task_now], eax               ;当前工作进程为系统进程
     add eax, proc_ctrl.next_task
     mov dword [eax], SYS_PROC          ;系统进程控制结构的下一个进程地址 指向自己
     mov eax, SYS_PROC
     add eax, proc_ctrl.state
     mov word [eax], task_running     ;工作进程状态为 正在运行

     popad
 
     ret
 
;-------------------------------------------------------------------------------
Load_usr_task:                            ;创建用户进程(权限3)
                                          ;输入参数: eax--用户进程的起始扇区号
            ;输入参数: ebx--用户进程扇区个数
            ;输入参数: ecx--进程PROC_CTRL结构的偏移地址
                                          ;输出参数: cx—-用户进程TSS段在gdt中的选择子         

     push eax                             ;[ebp + 24] 起始扇区号
     push ebx                           ;[ebp + 20] 扇区个数
     push ecx                             ;[ebp + 16] 进程控制结构proc_ctrl的偏移

     ;用户内存区分配用户“页目录”、“页表1”、“app页”、“用户堆栈esp3”三页
     call Alloc_usr_page
     push eax                           ;[ebp + 12] 页目录页
     call Alloc_usr_page
     push eax                             ;[ebp + 8] 页表1
     call Alloc_usr_page
     push eax                             ;[ebp + 4] app页
     call Alloc_usr_page
     push eax                             ;[ebp] 用户堆栈
     mov ebp, esp
 
     ;将用户页目录、页表1、app页映射到系统进程的前三页
     mov eax, [ebp + 12]
     or eax, 0x7
     mov dword [0xffc00000], eax
     mov eax, [ebp + 8]
     or eax, 0x7
     mov dword [0xffc00004], eax
     mov eax, [ebp + 4]
     or eax, 0x7
     mov dword [0xffc00008], eax
 
     ;拷贝系统页目录到用户页目录
     mov ecx, 1024
     xor edx, edx
_dir_cpy:
     mov eax, dword [0xfffff000 + edx]
     mov dword [edx], eax
     add edx, 4
     loop _dir_cpy

     ;用户页目录最后一项指向自己
     mov eax, [ebp + 12]
     or eax, 0x7
     mov dword [4092], eax
     ;用户页目录第一项指向页表1
     mov eax, [ebp + 8]
     or eax, 0x7
     mov dword [0], eax
     ;用户页表1第一项指向用户app页(对应线性地址:0x0-0x1000)
     mov eax, [ebp + 4]
     or eax, 0x7
     mov dword [0x1000], eax
     ;用户页表1第二项指向权限3堆栈(对应线性地址:0x1000-0x2000)
     mov eax, [ebp]
     or eax, 0x7
     mov dword [0x1004], eax
     ;将用户进程数据从逻辑扇区拷贝到到用户app页中
     mov eax, [ebp + 24]
     mov ebx, 0x2000
     mov ecx, [ebp + 20]

_cpy_disk:
     call read_hard_disk_0
     inc eax
     loop _cpy_disk
 
     ;将调用门信息写入用户进程
     mov ax, word [far_caller_1 + 4]
     mov [0x2004], ax
     mov ax, word [far_caller_2 + 4]
     mov [0x200a], ax
     mov ax, word [far_caller_3 + 4]
     mov [0x2010], ax
     mov ax, word [far_caller_4 + 4]
     mov [0x2016], ax
     mov ax, word [far_caller_5 + 4]
     mov [0x201c], ax
 
     ;初始化用户ldt段(代码段、数据段)
     mov eax, [ebp + 16]
     add eax, proc_ctrl.ldt
     mov dword [eax], ldt_code_low_dd
     mov dword [eax + 4], ldt_code_high_dd
     mov dword [eax + 8], ldt_data_low_dd
     mov dword [eax + 0x0c], ldt_data_high_dd
 
     ;将用户ldt段加入gdt
     call Set_LDT_sel
     mov eax, [ebp + 16]
     add eax, proc_ctrl.ldt_sel
     mov [eax], cx

     ;初始化用户进程TSS页,段内所有保留位都清空
     mov eax, [ebp + 16]
     add eax, proc_ctrl.tss
     push eax
     mov ecx, 26
     xor edx, edx
_init_usr_tss:
     mov dword [eax + edx], 0x0
     add edx, 4
     loop _init_usr_tss
 
     ;逐项填写TSS段
     call Alloc_sys_page                       ;分配用户进程使用的R0权限下的堆栈页
     mov edx, eax
     add edx, 4092                             ;esp0指针指向页的最后
     pop eax                                   ;恢复指向tss段的首地址
     mov dword [eax+0x4], edx                  ;esp0
     mov word [eax+0x8], flat_mode_data        ;ss0
     mov ebx, [ebp + 12]
     mov dword [eax+0x1c], ebx                 ;cr3
     mov dword [eax+0x20], 48                  ;eip
     pushfd
     pop ebx
     mov dword [eax+0x24], ebx                 ;eflag
     mov dword [eax+0x38], 0x2000-4            ;esp
     mov dword [eax+0x4c], 0x7                 ;cs(list-0,TI-1,RPL-3)
     mov dword [eax+0x50], 0x0f                ;ss(list-1,TI-1,RPL-3)
     mov dword [eax+0x54], 0x0f                ;ds(list-1,TI-1,RPL-3)
     mov ebx, [ebp + 16]
     add ebx, proc_ctrl.ldt_sel 
     mov cx, [ebx]
     mov word [eax+0x60], cx                   ;ldt选择子
     mov word [eax+0x66], 103                  ;TSS段长度

     ;将用户tss写入gdt
     call Set_TSS_sel
 
     ;修改进程状态为 正在运行
     mov eax, [ebp + 16]                       ;进程控制段
     add eax, proc_ctrl.state                  ;进程状态字段
     mov word [eax], task_running              ;进程状态字段设置为 正在运行             
 
     ;将进程控制段放入进程链表
     mov edx, [ebp + 16] 
     call mount_task_running_que
 
  ;将进程在gdt中的选择子写入进程结构进行保存
     mov edx, [ebp + 16] 
     mov [edx + proc_ctrl.task_sel], cx 
 
     ;绘制用户进程窗口 
     mov edx, [ebp + 16] 
     call draw_task_window
 
     add esp, 28    
 
     ret
 
;------------------------------------------------------------------------------- 
mount_task_running_que:                   ;将进程结构安装到运行队列中
                                          ;输入参数: edx--进程PROC_CTRL结构的偏移地址           
     cli                                  ;关中断
     pushad
    
     mov eax, [SYS_PROC + proc_ctrl.pre_task]  ;前一个进程结构地址
     mov [eax + proc_ctrl.next_task], edx      ;前一个进程的next指向新进程结构
     mov [SYS_PROC + proc_ctrl.pre_task], edx  ;系统进程的pre指向新进程结构
     mov [edx + proc_ctrl.pre_task], eax       ;新进程的pre指向前一个进程结构
     mov ebx, SYS_PROC                         ;新进程的next指向系统进程
     mov [edx + proc_ctrl.next_task], ebx     
 
     popad
     sti                                  ;开中断
     ret

;------------------------------------------------------------------------------- 
mount_task_run_to_pend_que:               ;将进程结构从就绪队列放入暂停队列 (在这里,由于系统进程不休眠,只有两个用户进程休眠,所以下面的代码偷懒了)           
                                          ;输入参数: edx--进程PROC_CTRL结构的偏移地址           
     cli                                  ;关中断
     pushad
     
     ;将进程结构从队列中取出
     mov eax, [edx + proc_ctrl.pre_task]  ;进程所在队列的前一个结构
     mov ebx, [edx + proc_ctrl.next_task] ;进程所在队列的后一个结构
     mov [_task_next], ebx                ;记录下一个进程结构地址
     mov [eax + proc_ctrl.next_task], ebx ;前一个结构的next指向后一个结构
     mov [ebx + proc_ctrl.pre_task], eax  ;后一个结构的pre指向前一个结构

     ;将进程结构放入pending队列
     cmp dword [_task_pend_que], 0x0      ;暂停队列是否为空
     jnz _chg_pnd_que1                    ;如果包含进程结构
     mov [_task_pend_que], edx            ;暂定队列头部指向该进程结构
     mov [edx + proc_ctrl.pre_task], edx  ;该进程结构的pre指向自己
     mov [edx + proc_ctrl.next_task], edx ;该进程结构的next指向自己
     jmp _chg_pnd_que2                    ;退出函数
 
_chg_pnd_que1:                            ;在这里,先被唤醒的放队列的前面,后被唤醒的放后面
     mov eax, dword[_task_pend_que]       ;eax指向暂定队列头部
     mov ecx, [edx + proc_ctrl.wakeup]    ;ecx指向新进程被唤醒的时刻值
     cmp ecx, [eax + proc_ctrl.wakeup]    ;和暂停队列头部比较唤醒时间大小
     jb _insert_head                      ;如果暂停时间小于头部时间,就插入暂停队列头部  
 
  ;插入暂停队列尾部
     mov ebx, [eax + proc_ctrl.pre_task]  ;ebx指向暂定队列的最后一个结构
     mov [ebx + proc_ctrl.next_task], edx ;队列最后一个结构的next指向本进程结构
     mov [eax + proc_ctrl.pre_task], edx  ;暂定队列头部的pre指向本进程结构
     mov [edx + proc_ctrl.pre_task], ebx  ;本进程结构的pre指向原队列最后一个结构
     mov [edx + proc_ctrl.next_task], eax ;本进程结构的next指向队列头部
     jmp _chg_pnd_que2

     ;插入暂停队列头部
_insert_head:
     mov eax, [_task_pend_que]            ;eax指向暂停队列头部
     mov [edx + proc_ctrl.next_task], eax ;本进程的next指向队列头部
     mov ebx, [eax + proc_ctrl.pre_task]  ;ebx指向暂定队列的最后一个结构
     mov [edx + proc_ctrl.pre_task], ebx
     mov [ebx + proc_ctrl.next_task], edx
     mov [eax + proc_ctrl.pre_task], edx
     mov [_task_pend_que], edx            ;暂停队列头部指向本结构

_chg_pnd_que2: 
     popad
     sti                                  ;开中断
 
     ;跳转到下一个就绪进程执行
     mov eax, [_task_next]                ;下一个进程结构地址
     mov [_task_now], eax                 ;当前进程
     add eax, proc_ctrl.task_rsvr
     jmp far [eax]                        ;跳转到新的进程执行
 
     ret

;------------------------------------------------------------------------------- 
mount_task_pend_to_run_que:               ;将进程结构从暂停队列放入就绪队列(就绪队列头部永远指向系统进程)            
                                          ;输入参数: edx--进程PROC_CTRL结构的偏移地址
     ;cli                                 ;关中断
     pushad

  ;先将进程结构从暂定队列取出
     mov edx, [_task_pend_que]            ;首先判断暂定队列是否只有一个结构
     mov eax, [edx + proc_ctrl.next_task] ;eax指向暂停队列头部的下一个结构
     cmp eax, edx                         ;如果暂停队列头部结构的next指向自己,暂停队列只有一个结构
     jnz _fix_pend_que_head 
     xor eax, eax
     mov [_task_pend_que], eax            ;暂停队列头部清空
     jmp _mount_to_run_que

_fix_pend_que_head:                       ;将暂停队列头部结构取出
     mov ebx, [edx + proc_ctrl.pre_task]  ;ebx指向暂停队列的尾部
     mov [ebx + proc_ctrl.next_task], eax ;尾部结构的next指向原队列的第二个结构
     mov [eax + proc_ctrl.pre_task], ebx  ;原队列的第二个结构的pre指向队列尾部结构
     mov [_task_pend_que], eax            ;暂停队列头部修改为原第二个结构地址

_mount_to_run_que: 
  ;将进程结构放入就绪队列
     mov eax, SYS_PROC                    ;eax指向系统进程
     mov ebx, [eax + proc_ctrl.pre_task]  ;ebx指向就绪队列最后一个结构
     mov [eax + proc_ctrl.pre_task], edx  ;系统进程的pre指向该进程结构
     mov [ebx + proc_ctrl.next_task], edx ;就绪队列最后一个结构的next指向该进程结构
     mov [edx + proc_ctrl.pre_task], ebx  ;该进程的pre指向队列原最后一个结构
     mov [edx + proc_ctrl.next_task], eax ;该进程的next指向系统进程结构 
 
     popad
     ;sti                                 ;开中断    
     ret 
 
;------------------------------------------------------------------------------- 
switch_task2:                               ;轮转切换当前执行的进程
    
     mov eax, [_task_now]                     ;eax指向当前进程
     mov ebx, [eax + proc_ctrl.next_task]     ;ebx指向下一个进程
     cmp eax, ebx                             ;是否是同一个进程
     je _switch_task_ok                       ;如果是同一个进程,无需切换
     mov [_task_now], ebx                     ;更新当前进程记录
     add ebx, proc_ctrl.task_rsvr
     jmp far [ebx]                            ;跳转到新的进程执行

_switch_task_ok:
     ret

;------------------------------------------------------------------------------- 
wakeup_task:                               ;检查进程休眠时间是否到时,并唤醒(在中断中处理,无需关中断)
    
     pushad 
     mov eax, [_task_pend_que]                ;eax指向休眠队列头部
     cmp eax, 0x0                             ;休眠队列是否为空
     jz wakeup_task_finished                  ;如果为空,直接跳出

     mov ebx, [sys_click]                     ;当前的系统时间
     mov ecx, [eax + proc_ctrl.wakeup]        ;ecx为进程被唤醒时间
     cmp ebx, ecx                             ;如果系统时间大于等于进程的唤醒时间
     jb wakeup_task_finished

     mov edx, eax                             ;调用时,edx指向被调整的进程地址
     call mount_task_pend_to_run_que        ;将进程结构从暂定队列放入就绪队列
   
wakeup_task_finished:
     popad
     ret 

;-------------------------------------------------------------------------------
draw_task_window:                             ;绘制用户进程窗口(窗口横梁宽度为5个点,其余都为一个点)
                                              ;输入:edx - 进程PROC_CTRL结构的偏移地址
     pushad
    
     ;窗口横梁,6个点宽
     xor eax, eax
     mov ax, 5                                ;eax高16位是y的高度
     shl eax, 16 
     mov ax, [edx + proc_ctrl.left_y]         ;eax低16位是y的值  
     xor ebx, ebx
     mov bx, [edx + proc_ctrl.len_x]          ;ebx高16位是x的宽度
     shl ebx, 16
     mov bx, [edx + proc_ctrl.left_x]         ;ebx低16位是x的值
     mov cl, 8
     call draw_rectangle                      ;画一个矩形
 
     ;窗口下梁,1个点宽
     xor eax, eax 
     mov ax, [edx + proc_ctrl.left_x]
     shl eax, 16 
     mov ax, [edx + proc_ctrl.left_y]
     add ax, [edx + proc_ctrl.len_y]
     xor ebx, ebx
     mov bx, [edx + proc_ctrl.len_x]
     mov cl, 8
     call draw_line 

     ;窗口左柱,1个点宽 
     xor eax, eax 
     mov ax, [edx + proc_ctrl.left_x]
     shl eax, 16 
     mov ax, [edx + proc_ctrl.left_y]
     xor ebx, ebx
     mov bx, [edx + proc_ctrl.len_y]
     mov cl, 8
     call draw_long_string 

     ;窗口右柱,1个点宽 
     xor eax, eax 
     mov ax, [edx + proc_ctrl.left_x]
     add ax, [edx + proc_ctrl.len_x]
     shl eax, 16 
     mov ax, [edx + proc_ctrl.left_y]
     xor ebx, ebx
     mov bx, [edx + proc_ctrl.len_y]
     inc bx
     mov cl, 8
     call draw_long_string
 
     ;窗口的退出按钮,大小为3×3的矩形
     xor eax, eax
     mov ax, 3                                ;eax高16位是y的高度
     shl eax, 16 
     mov ax, [edx + proc_ctrl.left_y]         ;eax低16位是y的值
     inc ax  
     xor ebx, ebx
     mov bx, 3                                ;ebx高16位是x的宽度
     shl ebx, 16
     mov bx, [edx + proc_ctrl.left_x]         ;ebx低16位是x的值
     add bx, [edx + proc_ctrl.len_x]
     sub bx, 4
     mov cl, 10                               ;暗绿
     call draw_rectangle                      ;画一个矩形     
    
     popad  
     ret            
 
;-------------------------------------------------------------------------------
read_hard_disk_0:                       ;从硬盘读取一个逻辑扇区(平坦模型)
          ;EAX=逻辑扇区号
          ;EBX=目标缓冲区线性地址
          ;返回:EBX=EBX+512
  cli
 
  push eax
  push ecx
  push edx
 
  push eax
 
  mov dx,0x1f2
  mov al,1
  out dx,al                          ;读取的扇区数

  inc dx                             ;0x1f3
  pop eax
  out dx,al                          ;LBA地址7~0

  inc dx                             ;0x1f4
  mov cl,8
  shr eax,cl
  out dx,al                          ;LBA地址15~8

  inc dx                             ;0x1f5
  shr eax,cl
  out dx,al                          ;LBA地址23~16

  inc dx                             ;0x1f6
  shr eax,cl
  or al,0xe0                         ;第一硬盘  LBA地址27~24
  out dx,al

  inc dx                             ;0x1f7
  mov al,0x20                        ;读命令
  out dx,al

.waits:
  in al,dx
  and al,0x88
  cmp al,0x08
  jnz .waits                         ;不忙,且硬盘已准备好数据传输

  mov ecx,256                        ;总共要读取的字数
  mov dx,0x1f0
.readw:
  in ax,dx
  mov [ebx],ax
  add ebx,2
  loop .readw

  pop edx
  pop ecx
  pop eax
 
  sti
 
  ret     

;--------------------------------全局变量---------------------------------------
align 4 
     _task_now        dd 0                    ;当前工作进程控制结构地址
     _task_next       dd 0                    ;当前工作进程的下一个结构
     _task_pend_que   dd 0x0                  ;暂停进程队列头
     _task_stop_que   dd 0x0                  ;停止进程队列头
     _task_old        dd 0                    ;保存上一个进程的控制结构地址 
     ;_task_window     dd 0                    ;按照顺序分配窗口(0-左下;1-右下;2-右上;左上角的窗口留给系统进程) 
 
SYS_PROC: 
     istruc proc_ctrl 
       at proc_ctrl.num,        resw    0 
       at proc_ctrl.state,      resw    0
       at proc_ctrl.wakeup,     resd    0
       at proc_ctrl.pre_task,   resd    0   
       at proc_ctrl.next_task,  resd    0   
       at proc_ctrl.task_rsvr,  resd    0
       at proc_ctrl.task_sel,   resw    0
       at proc_ctrl.ldt_rsvr,   resd    0
       at proc_ctrl.ldt_sel,    resw    0
       at proc_ctrl.ldt,        times   16 db 0
       at proc_ctrl.tss,     times   104 db 0
       at proc_ctrl.cmd,        times   8 db 0
       at proc_ctrl.sys_page,   resd    0
       at proc_ctrl.usr_page,   times   8 dd 0    
       at proc_ctrl.left_x,     resw    0
       at proc_ctrl.left_y,     resw    0
       at proc_ctrl.len_x,      resw    0
       at proc_ctrl.len_y,      resw    0   
     iend   
USR1_PROC: 
     istruc proc_ctrl 
       at proc_ctrl.num,        resw    0 
       at proc_ctrl.state,      resw    0
       at proc_ctrl.wakeup,     resd    0
       at proc_ctrl.pre_task,   resd    0   
       at proc_ctrl.next_task,  resd    0
       at proc_ctrl.task_rsvr,  resd    0
       at proc_ctrl.task_sel,   resw    0
       at proc_ctrl.ldt_rsvr,   resd    0
       at proc_ctrl.ldt_sel,    resw    0
       at proc_ctrl.ldt,        times   16 db 0
       at proc_ctrl.tss,     times   104 db 0
       at proc_ctrl.cmd,        times   8 db 0
       at proc_ctrl.sys_page,   resd    0
       at proc_ctrl.usr_page,   times   8 dd 0    
       at proc_ctrl.left_x,     resw    0
       at proc_ctrl.left_y,     resw    0
       at proc_ctrl.len_x,      resw    0
       at proc_ctrl.len_y,      resw    0
     iend
USR2_PROC: 
     istruc proc_ctrl 
       at proc_ctrl.num,        resw    0 
       at proc_ctrl.state,      resw    0
       at proc_ctrl.wakeup,     resd    0
       at proc_ctrl.pre_task,   resd    0   
       at proc_ctrl.next_task,  resd    0   
       at proc_ctrl.task_rsvr,  resd    0
       at proc_ctrl.task_sel,   resw    0
       at proc_ctrl.ldt_rsvr,   resd    0
       at proc_ctrl.ldt_sel,    resw    0
       at proc_ctrl.ldt,        times   16 db 0
       at proc_ctrl.tss,     times   104 db 0
       at proc_ctrl.cmd,        times   8 db 0
       at proc_ctrl.sys_page,   resd    0
       at proc_ctrl.usr_page,   times   8 dd 0    
       at proc_ctrl.left_x,     resw    0
       at proc_ctrl.left_y,     resw    0
       at proc_ctrl.len_x,      resw    0
       at proc_ctrl.len_y,      resw    0
     iend

align 4

1 0
原创粉丝点击