加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

使用call指令进行段间调用

(2011-04-20 13:58:58)
标签:

杂谈

分类: 汇编

保护模式中使用call指令调用远过程,一定要定义堆栈段


;===================================================
;16位偏移的段间调用宏指令
CALL16  MACRO   selector, offsetv
        DB      9AH             ;操作码
        DW      offsetv         ;16位偏移
        DW      selector        ;段值/选择子
        ENDM
;==================================================
;16位偏移的段间直接转换指令的宏定义
jump     macro  selector,offsetv
          db     0eah      ;操作码
          dw     offsetv   ;16位偏移
          dw     selector  ;段值或选择子
         endm

;====================================================
;存储段描述符结构类型的定义
descriptor  struc
limitl      dw         ;段界限(0--15)
basel       dw         ;段基地址(0--15)
basem       db         ;段基地址(16--23)
attributes  dw         ;段属性
baseh       db         ;段基地址(24--31)
descriptor  ends

;=======================================================
;伪描述符结构类型的定义
pdesc       struc
limit       dw         ;16界限
base        dd         ;基地址
pdesc       ends

;常量定义
atdw = 92h                ;存在的可读写数据段属性值
atce = 98h                ;存在的只执行代码段属性值
;atdr = 90h                ;data read only
atdwa=93h

;=========================================================
      .386P
;--------------------------------------------------------

;数据段
dseg        segment   use16     ;16位段
gdt         label   byte        ;全局描述符表gdt
dummy       descriptor <>       ;空描述符
;
code        descriptor <0ffffh,,,atce,>
code_sel    =code-gdt           ;代码段描述符的选择子
;
datas       descriptor <0ffffh,8000h,0bh,atdw,0>
datas_sel   =datas-gdt          ;源数据段描述符的选择子
;
stack       descriptor <0ffffh,,,atdwa,>   
stack_sel=stack-gdt             ;堆栈段
;
codec      descriptor
codec_sel  =codec-gdt          ;定义远过程短
;
gdtlen      =$-gdt
;
vgdtr        pdesc    ;伪描述符
;
varsp        dw  ?
varss        dw  ?
dseg         ends

;-------------------------------------------------------------
;堆栈段
stackseg    segment  use16  stack
            dw 512 dup(0)
stackseg    ends
;远过程代码段
codecseg    segment use16
            assume cs:codecseg
cstart     proc far
            mov si,10
            mov byte ptr [si],37h
            inc si
            mov byte ptr [si],07h
     ret
cstart     endp
codeclen   =$-cstart
codecseg    ends
;代码段
cseg        segment   use16     ; 16位段
            assume  cs:cseg, ds:dseg
start:
     mov ax,dseg
     mov ds,ax
     ;准备要加载到gdtr的伪描述符
     mov bx,16
     mul bx             ;计算并设置gdt基地址
     add ax,offset gdt  ;界限已在定义时设置妥当
     adc dx,0
     mov word ptr vgdtr.base,ax
     mov word ptr vgdtr.base+2,dx
     ;设置代码段描述符
     mov ax,cs
     mul bx
     mov code.basel,ax    ;代码段开始偏移为0
     mov code.basem,dl    ;代码段界限已在定义时设置妥当
     mov code.baseh,dh
     ;
     mov ax,codecseg
     mul bx
     mov codec.basel,ax    ;代码段开始偏移为0
     mov codec.basem,dl    ;代码段界限已在定义时设置妥当
     mov codec.baseh,dh
     ;
     mov ax,stackseg
     mul bx
     mov stack.basel,ax
     mov stack.basem,dl
     mov stack.baseh,dh
     ;
     mov varsp,sp
     mov varss,ss
     ;
     mov ax,0b800h
     mov ds,ax
     mov si,0
     mov ax,varsp ;这里可以输入想查的寄存器
     mov bx,ax
    
     and ax,0f000h
     mov cl,12
     shr ax,cl
     mov dl,al
     cmp dl,9
     ja s11
     add dl,30h
     jmp s21
   s11:add dl,37h
   s21:
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si

     mov ax,bx
     and ax,0f00h
     mov cl,8
     shr ax,cl
     mov dl,al
     cmp dl,9
     ja s31
     add dl,30h
     jmp s41
   s31:add dl,37h
   s41:
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si
 
     mov ax,bx
     and ax,0f0h
     mov cl,4
     shr ax,cl
     mov dl,al
     cmp dl,9
     ja s51
     add dl,30h
     jmp s61
   s51:add dl,37h
   s61:   
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si
 
     mov ax,bx
     and ax,0fh
     mov dl,al
     cmp dl,9
     ja s71
     add dl,30h
     jmp s81
   s71:add dl,37h
   s81:
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si
    
     ;加载gdtr
     mov ax,dseg
     mov ds,ax
     lgdt  fword ptr vgdtr
     ;
     cli                  ;关中断
     call ea20            ;打开地址线A20
     ;切换到保护模式
     mov eax,cr0
     or eax,1
     mov cr0,eax
     ;清指令预取队列,并真正进入保护模式
     jump ,
     ;
virtual:    ;现在开始在保护方式下
     mov ax,datas_sel
     mov ds,ax
     CALL16 codec_sel,cstart
     ;堆栈段
     mov ax,stack_sel
     mov ss,ax
    
     mov si,20
     mov ax,sp ;这里可以输入想查的寄存器
     mov bx,ax
    
     and ax,0f000h
     mov cl,12
     shr ax,cl
     mov dl,al
     cmp dl,9
     ja s1
     add dl,30h
     jmp s2
   s1:add dl,37h
   s2:mov ax,datas_sel
      mov ds,ax
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si

     mov ax,bx
     and ax,0f00h
     mov cl,8
     shr ax,cl
     mov dl,al
     cmp dl,9
     ja s3
     add dl,30h
     jmp s4
   s3:add dl,37h
   s4:mov ax,datas_sel
      mov ds,ax
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si
 
     mov ax,bx
     and ax,0f0h
     mov cl,4
     shr ax,cl
     mov dl,al
     cmp dl,9
     ja s5
     add dl,30h
     jmp s6
   s5:add dl,37h
   s6:mov ax,datas_sel
      mov ds,ax
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si
 
     mov ax,bx
     and ax,0fh
     mov dl,al
     cmp dl,9
     ja s7
     add dl,30h
     jmp s8
   s7:add dl,37h
   s8:mov ax,datas_sel
      mov ds,ax
      mov [si],dl
      inc si
      mov byte ptr [si],07h
      inc si
     ;
     ;切换回实模式
     mov eax,cr0
     and eax,0fffffffeh
     mov cr0,eax
     ;清指令预取队列,进入实方式
     jump ,
     ;
real:       ;现在又回到实方式
     ;mov ss,varss          ;恢复堆栈段
     mov ax,dseg
     mov ds,ax
     lss sp,dword ptr varsp
     call da20             ;关闭地址线A20
     sti                   ;开中断
     mov  ax,4c00h          ;结束
     int 21h
;
;打开地址线A20
ea20        proc
     push  ax
     in    al,92h
     or    al,2
     out   92h,al
     pop   ax
     ret
ea20        endp
;
;关闭地址线A20
da20        proc
     push  ax
     in    al,92h
     and   al,0fdh     ;0fdh=not 20h
     out   92h,al
     pop   ax
     ret
da20        endp
;
cseg        ends
            end  start

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有