当前位置: 代码迷 >> 汇编语言 >> 《自己动手写操作系统》于渊跟小弟我们开了个玩笑
  详细解决方案

《自己动手写操作系统》于渊跟小弟我们开了个玩笑

热度:6368   发布时间:2013-02-26 00:00:00.0
《自己动手写操作系统》于渊跟我们开了个玩笑
看过的朋友不知道还记不记得下面这两个宏
Descriptor
Gate
如果不记得,那么我可以提示一下
Assembly code
; 宏 ------------------------------------------------------------------------------------------------------;; 描述符; 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                (2 字节)    dw    %1 & 0FFFFh                ; 段基址 1                (2 字节)    db    (%1 >> 16) & 0FFh            ; 段基址 2                (1 字节)    dw    ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)    ; 属性 1 + 段界限 2 + 属性 2        (2 字节)    db    (%1 >> 24) & 0FFh            ; 段基址 3                (1 字节)%endmacro ; 共 8 字节;; 门; usage: Gate Selector, Offset, DCount, Attr;        Selector:  dw;        Offset:    dd;        DCount:    db;        Attr:      db%macro Gate 4    dw    (%2 & 0FFFFh)                ; 偏移 1                (2 字节)    dw    %1                    ; 选择子                (2 字节)    dw    (%3 & 1Fh) | ((%4 << 8) & 0FF00h)    ; 属性                    (2 字节)    dw    ((%2 >> 16) & 0FFFFh)            ; 偏移 2                (2 字节)%endmacro ; 共 8 字节; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

(copy自OS\Tinix\chapter3\e\pm.inc)

然后再看GDT那里
Assembly code
; 门                                            目标选择子,       偏移, DCount, 属性LABEL_CALL_GATE_TEST:    Gate          SelectorCodeDest,          0,      0, DA_386CGate + DA_DPL3

不知道大家有没有试过“DA_386CGate | DA_DPL3”,如果没试过,你可以试试。按理说都是位属性,那么为什么“加号”可以,而“或号”就不行了呢?
关键在于
Assembly code
dw    (%3 & 1Fh) | ((%4 << 8) & 0FF00h)    ; 属性                    (2 字节)

扩展后,其实“加号”的会被扩展为

Assembly code
 dw (0 & 0FFFFh) dw SelectorCodeDest dw (0 & 1Fh) | ((DA_386CGate + DA_DPL3 << 8) & 0FF00h) dw ((0 >> 16) & 0FFFFh)


而“或号”的会被扩展为
Assembly code
 dw (0 & 0FFFFh) dw SelectorCodeDest dw (0 & 1Fh) | ((DA_386CGate | DA_DPL3 << 8) & 0FF00h) dw ((0 >> 16) & 0FFFFh)

正确的时候生成的这个双字是
00 ec 00 00
与“加号”时是相同的
而“或号”生成的这个双字是
00 60 00 00



虽然示例代码并没有什么错误,但我还是将这两个宏修改了,因为它们不完美#109
下面是修改后的宏,这次再用我喜欢的“|”符号就没有问题啦#39
Assembly code
; 宏 ------------------------------------------------------------------------------------------------------;; 描述符; 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                (2 字节)    dw    (%1) & 0FFFFh                ; 段基址 1                (2 字节)    db    ((%1) >> 16) & 0FFh            ; 段基址 2                (1 字节)    dw    (((%2) >> 8) & 0F00h) | ((%3) & 0F0FFh)    ; 属性 1 + 段界限 2 + 属性 2        (2 字节)    db    ((%1) >> 24) & 0FFh            ; 段基址 3                (1 字节)%endmacro ; 共 8 字节;; 门; usage: Gate Selector, Offset, DCount, Attr;        Selector:  dw;        Offset:    dd;        DCount:    db;        Attr:      db%macro Gate 4    dw    ((%2) & 0FFFFh)                ; 偏移 1                (2 字节)    dw    (%1)                    ; 选择子                (2 字节)    dw    ((%3) & 1Fh) | (((%4) << 8) & 0FF00h)    ; 属性                    (2 字节)    dw    (((%2) >> 16) & 0FFFFh)            ; 偏移 2                (2 字节)%endmacro ; 共 8 字节
  相关解决方案