Linux下att语法的实模式向保护模式切换的试验

    .text
    .code16  #必须有,而且是code16
    .global _start

_start:
    jmp  LABEL_BEGIN    #ld -Ttext 0x7c00, 不要jmp  $LABEL_BEGIN
    #BOOTSEG     = 0x07C0
    #jmpl $BOOTSEG, $LABEL_BEGIN  #ld -Ttext 0x0
    LABEL_BEGIN:
        movw    %cs,%ax
        movw    %ax,%ds
        movw    %ax,%es
        movw    %ax,%ss
        #movw    $0x100,%sp  #有和用意?为了兼容com

        # 初始化 32 位代码段描述符
        xorl    %eax,%eax  #code16为何可以操作32为的寄存器? 16位指的是寻址,并不是不能使用32位寄存器. 如果改为.code32,为何编译成xor %ax,%ax了呢?
        movw    %cs,%ax
        shll    $4,%eax
        addl    $LABEL_SEG_CODE32, %eax
        movw    %ax, LABEL_DESC_CODE32 + 2
         shrl    $16,%eax
         movb    %al, LABEL_DESC_CODE32 + 4
        movb    %ah, LABEL_DESC_CODE32 + 7

        xorl    %eax,%eax
        movw    %ds,%ax
        shll    $4,%eax
        addl    $LABEL_GDT, %eax
        movl    %eax, GdtPtr + 2

        #; 加载 GDTR
         lgdt    GdtPtr

        cli
         # 打开地址线A20
        inb     $0x92,%al
        orb     $0b00000010,%al
        outb    %al, $0x92

         # 准备切换到保护模式
         #movl    $cr0, %eax
         #orl     $1,%eax
         #movl    %eax, $cr0
        movw    $1, %ax                # protected mode (PE) bit
        lmsw    %ax                    # This is it!


        #66ea000000000800    jmp far 0008:00000000
        .byte 0x66, 0xea            # prefix + jmpi-opcode
        .long    0
        .word   8  #.word   $SelectorCode32,不合法

        #ljmp   $8, $0x0   #ea00000800,  jmp far 0008:0000  #ljmp   $SelectorCode32, $0x,不合法

    .code32   #必须有,而且是code32
    #.text
    LABEL_SEG_CODE32:
            movw    $SelectorVideo, %ax
            movw    %ax,%gs                         # 视频段选择子(目的)

            movl     $((80 * 11 + 79) * 2), %edi     # 屏幕第 11 行, 第 79 列。
            movb    $0xC,%ah                        # 0000: 黑底    1100: 红字
            movb    $'P', %al
            movw    %ax, %gs:(%edi)                 #括号必须

            jmp     .
    SegCode32Len    =    . - LABEL_SEG_CODE32
    SelectorCode32    =    LABEL_DESC_CODE32 - LABEL_GDT
    SelectorVideo    =    LABEL_DESC_VIDEO  - LABEL_GDT

#.align 16
    LABEL_GDT:
    .byte    0
    .byte   0
    .byte    0
    .byte   0
    .byte    0
    .byte   0
    .byte    0
    .byte   0
    LABEL_DESC_CODE32:
    .byte    0x14
    .byte   0
    .byte    0
    .byte   0
    .byte    0
    .byte   0x98
    .byte    0x40
    .byte   0
    LABEL_DESC_VIDEO:
    .byte    0xff
    .byte   0xff
    .byte    0
    .byte   0x80
    .byte    0x0b
    .byte   0x92
    .byte    0
    .byte   0

    GdtLen =  . - LABEL_GDT    
    GdtPtr:
        .word    GdtLen - 1
        .long    0

#编译
#as -o a.bin attpmTest1.S 或者 gcc -c -o a.bin attpmTest1.S
#ld -Ttext 0x7c00 --oformat binary a.bin -o bootsect   //-Ttext 0x7c00加载地址,很关键, 或者     BOOTSEG = 0x07C0  jmpl $BOOTSEG, $LABEL_BEGIN
#dd if=bootsect of=a.img bs=512 count=1 conv=notrunc

#debug nasm版本的,把gdt的值初始化, 不知如何像nasm那样定义宏,宏的使用如下:
/*
.macro Descriptor p1,p2,p3
    .word    \p2 & 0xFFFF                # 段界限1, 前面必须加反斜线,十六进制必须是0x的,不能0FFFFh
    .word    \p1 & 0xFFFF                # 段基址1
    .byte    (\p1 >> 16) & 0xFF            # 段基址2
    .word    ((\p2 >> 8) & 0xF00) | (\p3 & 0xF0FF)    # 属性1 + 段界限2 + 属性2
    .byte    (\p1 >> 24) & 0xFF            # 段基址3
.endm

DA_32        =    0x4000    # 32 位段
DA_DRW        =    0x92    # 存在的可读写数据段属性值
DA_C        =    0x98    # 存在的只执行代码段属性值

LABEL_GDT:           Descriptor       0,                0, 0           # 空描述符,逗号也可用空格,常数前不用加$
LABEL_DESC_CODE32: Descriptor       0, (SegCode32Len - 1), (DA_C + DA_32) # 非一致代码段
LABEL_DESC_VIDEO:  Descriptor       0xB8000,   0xffff, DA_DRW            # 显存首地址
*/

#取相对地址时要使用$, 常数要使用$, 比如: movw    $SelectorVideo, %ax; addl    $LABEL_SEG_CODE32, %eax;  movl     $((80 * 11 + 79) * 2), %edi
#当前相对地址为.,而非$, 比如:GdtLen =  . - LABEL_GDT
#jmp    dword SelectorCode32:0, 改为写字节码的形式, 为何为8?指向第二个描述符
#LABEL_SEG_CODE32中的.code32不可少。
#nasm注释为;,而att为#
#反汇编:objdump -D -b binary -m i8086 -M att
#objdump -b binary -s ,现实16进制数据,与hexdump   、xxd对比
#file命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值