Chinaunix首页 | 论坛 | 博客
  • 博客访问: 173628
  • 博文数量: 47
  • 博客积分: 992
  • 博客等级: 准尉
  • 技术积分: 565
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-08 21:57
文章分类

全部博文(47)

文章存档

2019年(1)

2018年(1)

2017年(1)

2014年(6)

2013年(1)

2012年(2)

2011年(35)

我的朋友

分类: LINUX

2011-06-15 11:29:44

Kernel110615: bioscall.S注记


Email:    zcatt@163.com
Blog    http://zcatt.blog.chinaunix.net
 
声明
仅限学习交流,禁止商业用途。转载需注明出处。

版本记录
Date        Ver        Note
2011-06-15    0.1        Draft.  zcatt, Beijing


kernel/arch/x86/boot/bioscall.S实现了c函数intcall(), 原型如下,
    
    void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);

其中biosregs计44bytes.

    struct biosregs {
        union {
            struct {
                u32 edi;
                u32 esi;
                u32 ebp;
                u32 _esp;
                u32 ebx;
                u32 edx;
                u32 ecx;
                u32 eax;
                u32 _fsgs;
                u32 _dses;
                u32 eflags;
            };
            struct {
                u16 di, hdi;
                u16 si, hsi;
                u16 bp, hbp;
                u16 _sp, _hsp;
                u16 bx, hbx;
                u16 dx, hdx;
                u16 cx, hcx;
                u16 ax, hax;
                u16 gs, fs;
                u16 es, ds;
                u16 flags, hflags;
            };
            struct {
                u8 dil, dih, edi2, edi3;
                u8 sil, sih, esi2, esi3;
                u8 bpl, bph, ebp2, ebp3;
                u8 _spl, _sph, _esp2, _esp3;
                u8 bl, bh, ebx2, ebx3;
                u8 dl, dh, edx2, edx3;
                u8 cl, ch, ecx2, ecx3;
                u8 al, ah, eax2, eax3;
            };
        };
    };

c调用intcall()时, eax, edx和ecx分别容纳int_no, ireg, 和oreg.

bioscall.S的详细注释如下,

/* -----------------------------------------------------------------------
 *
 *   Copyright 2009 Intel Corporation; author H. Peter Anvin
 *
 *   This file is part of the Linux kernel, and is made available under
 *   the terms of the GNU General Public License version 2 or (at your
 *   option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * "Glove box" for BIOS calls.  Avoids the constant problems with BIOSes
 * touching registers they shouldn't be.
 */
/*zcatt, 原型, void intcall(byte int_no -- %eax), biosregs *ireg -- %edx, biosregs *oreg -- %ecx) */
    .code16gcc
    .text
    .globl    intcall
    .type    intcall, @function    /*zcatt, intcall是function */
intcall:
    /* Self-modify the INT instruction.  Ugly, but works. */
    cmpb    %al, 3f        /*zcatt, %al是int_no */
    je    1f        /*zcatt, if already set, pass */
    movb    %al, 3f        /*zcatt, int_no写道下面的中断指令参数中 */
    jmp    1f        /* Synchronize pipeline */ /*zcatt, 这个很重要 */
1:
    /* Save state */    /*zcatt, 保存现场, 函数退出时复原 */
    pushfl            /*zcatt, push %eflag, 4byte */
    pushw    %fs        /*zcatt, push %fs, 2byte */
    pushw    %gs        /*zcatt, push %gs, 2byte */
    pushal            /*zcatt, push %eax, %ecx, %edx, %ebx, %esp, %ebp, %esi, %edi, 计4byte*8 */
        /*zcatt, 至此, 栈的内容从高到底是, 其中eip是caller的call语句压入的: ip, eflag, fsgs, eax, ecx, edx, ebx, esp, ebp, esi, edi */
    /* Copy input state to stack frame */
    subw    $44, %sp    /*zcatt, 分配栈空间, 容纳ireg */
    movw    %dx, %si    /*zcatt, %dx是intcall()的入口参数ireg */
    movw    %sp, %di
    movw    $11, %cx
    rep; movsd        /*zcatt, caller的ireg内容写入栈[%sp, $44(%sp)] */

    /* Pop full state from the stack */ /*zcatt, 栈内的ireg内容装入到各自寄存器中 */
    popal
    popw    %gs
    popw    %fs
    popw    %es
    popw    %ds
    popfl

    /* Actual INT */
    .byte    0xcd        /* INT opcode */    /*zcatt, 原始的办法, 凑intr指令 */
3:    .byte    0        /*zcatt, intNo已经在之前设置好 */

    /* Push full state to the stack */ /*zcatt, intr后的结果按照oreg的格式保存到栈中 */
    pushfl
    pushw    %ds
    pushw    %es
    pushw    %fs
    pushw    %gs
    pushal

    /* Re-establish C environment invariants */ /*zcatt, intcall的调用者应当是c程序,  */
    cld
    movzwl    %sp, %esp
    movw    %cs, %ax
    movw    %ax, %ds
    movw    %ax, %es

    /* Copy output state from stack frame */
    movw    68(%esp), %di    /* Original %cx == 3rd argument */ /*zcatt, ecx是oreg的地址, 现在的栈情况: eip, eflag, fsgs, eax, ECX, edx, ebx, esp, ebp, esi, edi, oreg的内容(44bytes). 到cx的距离合计44+4byte*8=68bytes */
    andw    %di, %di
    jz    4f
    movw    %sp, %si
    movw    $11, %cx
    rep; movsd        /*zcatt, 栈中的oreg内容写入到caller的oreg地址 */
4:    addw    $44, %sp    /*zcatt, 退出栈中的oreg内容 */

    /* Restore state and return */    /*zcatt, 退出前复原 */
    popal
    popw    %gs
    popw    %fs
    popfl
    retl
    .size    intcall, .-intcall    /*zcatt, 设定intcall函数的大小 */


Locations of visitors to this page
阅读(1427) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

zcatt2011-11-10 08:37:29

starli22: c调用intcall()时, eax, edx和ecx分别容纳int_no, ireg, 和oreg.
请问为什么是这个样子的?参数不通过堆栈传递的么?.....
少参数直接使用reg传递.

starli222011-10-22 14:25:16

c调用intcall()时, eax, edx和ecx分别容纳int_no, ireg, 和oreg.
请问为什么是这个样子的?参数不通过堆栈传递的么?