Orange'S 第三章第二节实验

来源:互联网 发布:淘宝规定卖家发货时间 编辑:程序博客网 时间:2024/06/05 04:51

这个实验没有完全按照书上的来,这个实验对比第一小节只是增加了栈段,有了栈,就可以安全的使用C函数了

desc.h 代码

#include <stdint.h>// Type field#define TYPE_DATA_RO          0#define TYPE_DATA_RO_A        1#define TYPE_DATA_RW          2#define TYPE_DATA_RW_A        3#define TYPE_DATA_RO_E        4#define TYPE_DATA_RO_E_A      5#define TYPE_DATA_RW_E        6#define TYPE_DATA_RW_E_A      7#define TYPE_CODE_XO          8#define TYPE_CODE_XO_A        9#define TYPE_CODE_XR          10#define TYPE_CODE_XR_A        11#define TYPE_CODE_XO_C        12#define TYPE_CODE_XO_C_A      13#define TYPE_CODE_XR_C        14#define TYPE_CODE_XR_C_A      15#define TYPE_SYS_TSS_16_A     1#define TYPE_SYS_LDT          2#define TYPE_SYS_TSS_16_B     3#define TYPE_SYS_CALL_GATE_16 4#define TYPE_SYS_TASK_GATE    5#define TYPE_SYS_INT_GATE_16  6#define TYPE_SYS_TRAP_GATE_16 7#define TYPE_SYS_TSS_32_A     9#define TYPE_SYS_TSS_32_B     11#define TYPE_SYS_CALL_GATE_32 12#define TYPE_SYS_INT_GATE_32  14#define TYPE_SYS_TRAP_GATE_32 15// S(descripor type) flag#define DESC_TYPE_SYSTEM 0#define DESC_TYPE_CODE   1#define DESC_TYPE_DATA   1// DPL(descriptor privilege level) field#define DPL_0 0#define DPL_1 1#define DPL_2 2#define DPL_3 3// P(segment-present) flag#define SEG_PRESENT     1#define SEG_NOT_PRESENT 0// D/B flag#define CODE_32         1#define CODE_16         0#define DATA_32         1#define DATA_16         0// G(granularity) flag#define G_BYTE    0#define G_4K_BYTE 1typedef struct __attribute__((packed)) {    uint16_t limit;    uint32_t base;} gdtr_t;typedef struct {    uint16_t rpl:2;    uint16_t ti:1;    uint16_t index:13;} seg_selector_t;typedef struct {    uint64_t limit_15_0:16;    uint64_t base_23_0:24;    uint64_t type:4;    uint64_t s:1;    uint64_t dpl:2;    uint64_t p:1;    uint64_t limit_19_16:4;    uint64_t avl:1;    uint64_t res:1;    uint64_t db:1;    uint64_t g:1;    uint64_t base_31_24:8;} seg_desc_t;#define SEG_DESC(_base, _limit, _type, _s, _dpl, _p, _db, _g) { \        .base_23_0 = (_base) & 0xffffff,         \        .base_31_24 = ((_base) >> 24) & 0xff, \        .limit_15_0 = (_limit) & 0xffff, \            .limit_19_16 = ((_limit) >> 16) & 0xf, \            .type = (_type), \            .s = (_s), \            .dpl = (_dpl), \            .p = (_p), \            .avl = 0, \            .res = 0, \            .db = (_db), \            .g = (_g), \}

desc.h 相对第一小节没有变化

gdt.c 这里文件定义了全局描述符表,即全局描述符表指针

#include "desc.h"seg_desc_t gdt[] = {    // null    [0] = SEG_DESC(0, 0, 0, 0, 0, 0, 0, 0),    // code32    [1] = SEG_DESC(0x7c80, 0xff, TYPE_CODE_XO, DESC_TYPE_CODE, DPL_0, SEG_PRESENT, CODE_32, G_BYTE),    // stack    [2] = SEG_DESC(0x500000, 0xfffff, TYPE_DATA_RW, DESC_TYPE_DATA, DPL_0, SEG_PRESENT, DATA_32, G_BYTE),    // video    [3] = SEG_DESC(0xb8000, 0xffff, TYPE_DATA_RW, DESC_TYPE_DATA, DPL_0, SEG_PRESENT, DATA_32, G_BYTE),};gdtr_t gdtr = {    .limit = sizeof(gdt)-1,    .base = (uint32_t)&gdt,};

gdt相对于第一小节,添加了一个栈段描述符,段基地址设为5M,为了演示突破1M的访问范围

boot.S 代码

#define CODE_SELECTOR  (1 << 3)#define STACK_SELECTOR (2 << 3)#define VIDEO_SELECTOR (3 << 3)    .code16    .section text16    .globl _start_start:    cli    # load gdtr    lgdt gdtr    # enable a20    inb $0x92, %al    orb $0b10, %al    outb %al, $0x92    # enable pm    movl %cr0, %eax    orl $0x01, %eax    movl %eax, %cr0    # jump to pm    jmpl $CODE_SELECTOR, $0x0    hlt    .code32    .section text32    movw $STACK_SELECTOR, %ax    movw %ax, %ss    movw $VIDEO_SELECTOR, %ax    movw %ax, %gs    call main

boot.S 在进入保护模式后,只进行了栈段,和视频段的初始化,然后跳到main函数

main.c 代码

#include <stdint.h>typedef union {    struct {        uint8_t c;       // al        uint8_t attr;    // ah    };    uint16_t value;          // ax} attr_char_t;void display_char(attr_char_t ac, int pos){    asm volatile("movw %0, %%gs:(%1)\n\t"             :             : "a"(ac.value), "D"(pos));}void display_attr_string(const char *str, uint8_t attr, int pos){    for (; *str; ++str, pos+=2) {        attr_char_t c = { *str, attr };        display_char(c, pos);    }}int main(){    display_attr_string("hello, world", 0x0c, 200);}

c函数可以使用栈变量了,比如函数参数

#### boot.lds

OUTPUT_FORMAT(binary)ENTRY(_start)MEMORY {       boot_region (RX) : org = 0x7c00, len = 512}SECTIONS {     .text : {         boot.o(text16)         . = 64;         gdt.o(.data*)         . = 128;         boot.o(text32)         *(.text .rodata)         . = 510;         SHORT(0xaa55)     } >boot_region     /DISCARD/ : {           *(*)     }}

Makefile

OBJECTS = boot.o gdt.o main.oCFLAGS = -fno-pic -cLDFLAGS = -Tboot.ldsa.img: boot.bin    -rm a.img    bximage -q -mode=create -fd=1.44M a.img    dd if=boot.bin of=a.img bs=512 count=1 conv=notruncboot.bin: $(OBJECTS) boot.lds    ld $(LDFLAGS) $(OBJECTS) -o boot.bin    ld $(LDFLAGS) $(OBJECTS) --oformat=elf32-i386 -o boot.elf  # for objdumpboot.o: boot.S    gcc $(CFLAGS) boot.Sgdt.o: gdt.c desc.h    gcc $(CFLAGS) gdt.cmain.o: main.c    gcc $(CFLAGS) main.c.PHONY: cleanclean:    -rm $(OBJECTS) boot.bin boot.elf a.img

效果

这里写图片描述