orange's一个操作系统的实现--学习过程 第三章:a代码反汇编分析

版权声明:原创作者:http://blog.csdn.net/port23 。 欢迎讨论转载,请注明来源: https://blog.csdn.net/port23/article/details/81323544

因为汇编语言编译的二进制程序在内存中和本身文件是一样的,把汇编出来的pmtest1.bin文件的16进制复制出来分析一下
(区别是文件只能看到静态结果,无法执行)

可以通过bochs调试模式,一步一步的执行,观察gdt数据结构的变化。
虽然是CPU支持保护模式的gdt方式,但是需要程序自己构造数据结构保存数据,程序自己动态的使用自己的数据。


--汇编出来的二进制文件pmtest1.bin文件
00000000h: E9 21 00 00 00 00 00 00 00 00 00 00 14 00 00 00 ; ?..............
00000010h: 00 98 40 00 FF FF 00 80 0B 92 00 00 17 00 00 00 ; .楡..€.?.....
00000020h: 00 00 00 00 8C C8 8E D8 8E C0 8E D0 BC 00 01 66 ; ....屓庁幚幮?.f
00000030h: 31 C0 8C C8 66 C1 E0 04 66 05 80 7C 00 00 A3 0E ; 1缹萬拎.f.€|..?
00000040h: 7C 66 C1 E8 10 A2 10 7C 88 26 13 7C 66 31 C0 8C ; |f凌.?|?.|f1缹
00000050h: D8 66 C1 E0 04 66 05 04 7C 00 00 66 A3 1E 7C 0F ; 豧拎.f..|..f?|.
00000060h: 01 16 1C 7C FA E4 92 0C 02 E6 92 0F 20 C0 66 83 ; ...|?.鎾. 纅?
00000070h: C8 01 0F 22 C0 66 EA 00 00 00 00 08 00 00 00 00 ; ?."纅?........
00000080h: 66 B8 10 00 8E E8 BF 7E 07 00 00 B4 0C B0 50 65 ; f?.庤縹...?癙e
00000090h: 66 89 07 EB FE                                  ; f?膻


----------使用bochs调试模式进行反汇编
--前3个字节是一个jmp指令  
00007c00: (                    ): jmp .+33                  ; e92100
E9 21 00 
--多了一个字节00 不知道为什么    ----------因为段是4字节对齐的即段的长度是4字节的倍数。NASM对于每个SECTION,默认按4字节对齐。 
--对应源码
org    07c00h
    jmp    LABEL_BEGIN

--bochs调试
<bochs:1> b 0x7c00
<bochs:2> c
(0) Breakpoint 1, 0x0000000000007c00 in ?? ()
Next at t=65538738
(0) [0x000000007c00] 0000:7c00 (unk. ctxt): jmp .+33 (0x00007c24)     ; e92100
<bochs:3> u /16 0x7c00
00007c00: (                    ): jmp .+33                  ; e92100
00007c03: (                    ): add byte ptr ds:[bx+si], al ; 0000
00007c05: (                    ): add byte ptr ds:[bx+si], al ; 0000
00007c07: (                    ): add byte ptr ds:[bx+si], al ; 0000

--3个gdt(每个8个字节)
00 00 00 00 00 00 00 00 
14 00 00 00 00 98 40 00
FF FF 00 80 0B 92 00 00

<bochs:8> x /24bx  0x7c04
[bochs]:
0x0000000000007c04 <bogus+       0>:    0x00    0x00    0x00    0x00    0x00  0x00    0x00    0x00
0x0000000000007c0c <bogus+       8>:    0x14    0x00    0x00    0x00    0x00  0x98    0x40    0x00
0x0000000000007c14 <bogus+      16>:    0xff    0xff    0x00    0x80    0x0b  0x92    0x00    0x00

--源码
LABEL_GDT:           Descriptor       0,                0, 0           ; 空描述符
LABEL_DESC_CODE32:     Descriptor       0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段
LABEL_DESC_VIDEO:      Descriptor 0B8000h,           0ffffh, DA_DRW         ; 显存首地址
; GDT 结束                          

DA_32        EQU    4000h    ; 32 位段
DA_C        EQU    98h    ; 存在的只执行代码段属性值
DA_DRW        EQU    92h    ; 存在的可读写数据段属性值


; 描述符
; usage: Descriptor Base, Limit, Attr
;        Base:  dd
;        Limit: dd (low 20 bits available)
;        Attr:  dw (lower 4 bits of higher byte are always 0)
%macro Descriptor 3
    dw    %2 & 0FFFFh                ; 段界限1
    dw    %1 & 0FFFFh                ; 段基址1
    db    (%1 >> 16) & 0FFh            ; 段基址2
    dw    ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)    ; 属性1 + 段界限2 + 属性2
    db    (%1 >> 24) & 0FFh            ; 段基址3
%endmacro ; 共 8 字节


; 图示二

; 高地址………………………………………………………………………低地址; |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0    |
; |7654321076543210765432107654321076543210765432107654321076543210|    <- 共 8 字节
; |--------========--------========--------========--------========|
; ┏━━━┳━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┓
; ┃31..24┃   (见下图)   ┃     段基址(23..0)    ┃ 段界限(15..0)┃
; ┃      ┃              ┃                      ┃              ┃
; ┃ 基址2┃③│②│    ①  ┃基址1b │   基址1a     ┃    段界限1   ┃
; ┣━━━╋━━━┳━━━╋━━━━━━━━━━━╋━━━━━━━┫
; ┃   %6 ┃  %5  ┃  %4  ┃  %3  ┃     %2       ┃       %1     ┃
; ┗━━━┻━━━┻━━━┻━━━┻━━━━━━━┻━━━━━━━┛
;         │                \_________
;         │                          \__________________
;         │                                             \________________________________________________
;         │                                                                                              \
;         ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
;         ┃ 7  ┃ 6  ┃ 5  ┃ 4  ┃ 3  ┃ 2  ┃ 1  ┃ 0  ┃ 7  ┃ 6  ┃ 5  ┃ 4  ┃ 3  ┃ 2  ┃ 1  ┃ 0  ┃
;         ┣━━╋━━╋━━╋━━╋━━┻━━┻━━┻━━╋━━╋━━┻━━╋━━╋━━┻━━┻━━┻━━┫
;         ┃ G  ┃ D  ┃ 0  ┃ AVL┃   段界限 2 (19..16)  ┃  P ┃   DPL    ┃ S  ┃       TYPE           ┃
;         ┣━━┻━━┻━━┻━━╋━━━━━━━━━━━╋━━┻━━━━━┻━━┻━━━━━━━━━━━┫
;         ┃      ③: 属性 2      ┃    ②: 段界限 2      ┃                   ①: 属性1                  ┃
;         ┗━━━━━━━━━━━┻━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛
;       高地址                                                                                          低地址
;
;
--文件内容
17 00 00 00 00 00
--源码
GdtLen        equ    $ - LABEL_GDT    ; GDT长度
GdtPtr        dw    GdtLen - 1    ; GDT界限 ==23
        dd    0        ; GDT基地址


--从开始段已经过去34个字节  有2个字节的00  ----------因为每个段都是4字节对齐的即段的长度是4字节的倍数
00 00 

--已经过去36个字节即0x24个字节 反编译一下   是第一个指令跳转过来的地方
<bochs:23> u /16 0x7c24  
00007c24: (                    ): mov ax, cs                ; 8cc8
00007c26: (                    ): mov ds, ax                ; 8ed8
00007c28: (                    ): mov es, ax                ; 8ec0
00007c2a: (                    ): mov ss, ax                ; 8ed0
00007c2c: (                    ): mov sp, 0x0100            ; bc0001

--源码
[SECTION .s16]
[BITS    16]
LABEL_BEGIN:
    mov    ax, cs
    mov    ds, ax
    mov    es, ax
    mov    ss, ax
    mov    sp, 0100h

--二进制文件内容
8C C8 8E D8 8E C0 8E D0 BC 00 01 

--从0x2f个字节 反编译一下
<bochs:12> u /16 0x7c2f
00007c2f: (                    ): xor eax, eax              ; 6631c0
00007c32: (                    ): mov ax, cs                ; 8cc8
00007c34: (                    ): shl eax, 0x04             ; 66c1e004
00007c38: (                    ): add eax, 0x00007c80       ; 6605807c0000
00007c3e: (                    ): mov word ptr ds:0x7c0e, ax ; a30e7c
00007c41: (                    ): shr eax, 0x10             ; 66c1e810
00007c45: (                    ): mov byte ptr ds:0x7c10, al ; a2107c
00007c48: (                    ): mov byte ptr ds:0x7c13, ah ; 8826137c


--源码
    ; 初始化 32 位代码段描述符
    xor    eax, eax
    mov    ax, cs
    shl    eax, 4
    add    eax, LABEL_SEG_CODE32
    mov    word [LABEL_DESC_CODE32 + 2], ax
    shr    eax, 16
    mov    byte [LABEL_DESC_CODE32 + 4], al
    mov    byte [LABEL_DESC_CODE32 + 7], ah


--二进制文件内容
66 31 C0 8C C8 66 C1 E0 04 66 05 80 7C 00 00 A3 0E 
7C 66 C1 E8 10 A2 10 7C 88 26 13 7C 

--从0x4c个字节 反编译一下
<bochs:13> u /16 0x7c4c
00007c4c: (                    ): xor eax, eax              ; 6631c0
00007c4f: (                    ): mov ax, ds                ; 8cd8
00007c51: (                    ): shl eax, 0x04             ; 66c1e004
00007c55: (                    ): add eax, 0x00007c04       ; 6605047c0000
00007c5b: (                    ): mov dword ptr ds:0x7c1e, eax ; 66a31e7c
00007c5f: (                    ): lgdt ds:0x7c1c            ; 0f01161c7c
00007c64: (                    ): cli                       ; fa
00007c65: (                    ): in al, 0x92               ; e492
00007c67: (                    ): or al, 0x02               ; 0c02
00007c69: (                    ): out 0x92, al              ; e692
00007c6b: (                    ): mov eax, cr0              ; 0f20c0
00007c6e: (                    ): or eax, 0x00000001        ; 6683c801
00007c72: (                    ): mov cr0, eax              ; 0f22c0
00007c75: (                    ): jmpf 0x0008:00000000      ; 66ea000000000800


--源码
    ; 为加载 GDTR 作准备
    xor    eax, eax
    mov    ax, ds
    shl    eax, 4
    add    eax, LABEL_GDT        ; eax <- gdt 基地址
    mov    dword [GdtPtr + 2], eax    ; [GdtPtr + 2] <- gdt 基地址

    ; 加载 GDTR
    lgdt    [GdtPtr]

    ; 关中断
    cli

    ; 打开地址线A20
    in    al, 92h
    or    al, 00000010b
    out    92h, al

    ; 准备切换到保护模式
    mov    eax, cr0
    or    eax, 1
    mov    cr0, eax

    ; 真正进入保护模式
    jmp    dword SelectorCode32:0    ; 执行这一句会把 SelectorCode32 装入 cs,
                    ; 并跳转到 Code32Selector:0  处
; END of [SECTION .s16]
--二进制文件内容
66 31 C0 8C 
D8 66 C1 E0 04 66 05 04 7C 00 00 66 A3 1E 7C 0F 
01 16 1C 7C FA E4 92 0C 02 E6 92 0F 20 C0 66 83 
C8 01 0F 22 C0 
66 EA 00 00 00 00 08 00 

--因为每个段都是4字节对齐的  补位3个字节0x00
00 00 00 

--从0x80个字节 反编译一下

由于从这儿开始是32位代码段,需要主动指定反编译代码段的大小

<bochs:18> u size=32
<bochs:19> u /16  0x7c80
00007c80: (                    ): mov ax, 0x0010            ; 66b81000
00007c84: (                    ): mov gs, ax                ; 8ee8
00007c86: (                    ): mov edi, 0x0000077e       ; bf7e070000
00007c8b: (                    ): mov ah, 0x0c              ; b40c
00007c8d: (                    ): mov al, 0x50              ; b050
00007c8f: (                    ): mov word ptr gs:[edi], ax ; 65668907
00007c93: (                    ): jmp .-2                   ; ebfe
00007c95: (                    ): add byte ptr ds:[eax], al ; 0000
00007c97: (                    ): add byte ptr ds:[eax], al ; 0000
00007c99: (                    ): add byte ptr ds:[eax], al ; 0000


--源码
[SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS    32]

LABEL_SEG_CODE32:
    mov    ax, SelectorVideo
    mov    gs, ax            ; 视频段选择子(目的)

    mov    edi, (80 * 11 + 79) * 2    ; 屏幕第 11 行, 第 79 列。
    mov    ah, 0Ch            ; 0000: 黑底    1100: 红字
    mov    al, 'P'
    mov    [gs:edi], ax

    ; 到此停止
    jmp    $

--二进制文件内容
66 B8 10 00 8E E8 BF 7E 07 00 00 B4 0C B0 50 65 
66 89 07 EB FE      

猜你喜欢

转载自blog.csdn.net/port23/article/details/81323544