Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 我对A20行检查代码的理解正确吗?_Assembly_X86 16_Bootloader - Fatal编程技术网

Assembly 我对A20行检查代码的理解正确吗?

Assembly 我对A20行检查代码的理解正确吗?,assembly,x86-16,bootloader,Assembly,X86 16,Bootloader,我一直在关注如何检查和启用A20线路。我想我明白了,但有人能帮我澄清一下吗 已经在该教程中的注释开始, 我的评论开始 如果我不理解某些部分,您能解释一下原因吗?代码正在检查FFFF:0510和0000:0500是否通过同时写入两个地址来引用相同的地址,并查看写入一个地址是否会覆盖另一个地址 事实证明,FFFF:0510可以表示线性地址0x100500,而不是0x500,但前提是启用了A20。因此,代码将所有零写入es:di(aka0000:0500)处的字节,所有1写入ds:si(akaFFFF

我一直在关注如何检查和启用A20线路。我想我明白了,但有人能帮我澄清一下吗

已经在该教程中的注释开始

我的评论开始


如果我不理解某些部分,您能解释一下原因吗?

代码正在检查
FFFF:0510
0000:0500
是否通过同时写入两个地址来引用相同的地址,并查看写入一个地址是否会覆盖另一个地址

事实证明,
FFFF:0510
可以表示线性地址
0x100500
,而不是
0x500
,但前提是启用了A20。因此,代码将所有零写入
es:di
(aka
0000:0500
)处的字节,所有1写入
ds:si
(aka
FFFF:0510
)处的字节。如果启用A20,则两个段:偏移对引用不同的地址,第一次写入将保持不变,并且
[es:di]
将包含零。否则,两对引用相同的地址,第二次写入将与第一次写入相反,并且
[es:di]
将包含
0xff


(顺便说一下,
0x55
0xAA
不属于这一部分;我不确定这些数字是从哪里来的。引导签名通常位于0x7dfe,IIRC。)

代码正在检查
FFFF:0510
0000:0500
是否引用了相同的地址,方法是同时写入两个地址,并查看写入一个地址是否会覆盖另一个地址

事实证明,
FFFF:0510
可以表示线性地址
0x100500
,而不是
0x500
,但前提是启用了A20。因此,代码将所有零写入
es:di
(aka
0000:0500
)处的字节,所有1写入
ds:si
(aka
FFFF:0510
)处的字节。如果启用A20,则两个段:偏移对引用不同的地址,第一次写入将保持不变,并且
[es:di]
将包含零。否则,两对引用相同的地址,第二次写入将与第一次写入相反,并且
[es:di]
将包含
0xff


(顺便说一句,
0x55
0xAA
不属于这一部分;我不确定这些数字是从哪里来的。引导签名通常位于0x7dfe,IIRC。)

我想你错过了维基中的这一行:

下面的代码执行检查(与上面描述的不同——更直接)

如果禁用A20,则这两个位置将互相别名。如果没有,他们就没有。这就是为什么它会存储两个不同的值,然后检查其中有什么。(无论第二个存储是否有别名。)

如果您在高位地址检查0xAA55签名,您将只进行加载。另外,地址(
FFFF:0500
0000:0510
)不等于
0000:7DFE
(引导扇区签名的位置)和
FFFF:7E0E
(可能是别名),即使在标准化之后也是如此


你用稀薄的空气制造了AA和55;它们不会出现在代码中的任何地方,也不会从您找到它们的地址加载。

我想您错过了wiki中的这一行:

下面的代码执行检查(与上面描述的不同——更直接)

如果禁用A20,则这两个位置将互相别名。如果没有,他们就没有。这就是为什么它会存储两个不同的值,然后检查其中有什么。(无论第二个存储是否有别名。)

如果您在高位地址检查0xAA55签名,您将只进行加载。另外,地址(
FFFF:0500
0000:0510
)不等于
0000:7DFE
(引导扇区签名的位置)和
FFFF:7E0E
(可能是别名),即使在标准化之后也是如此


你用稀薄的空气制造了AA和55;它们不会出现在代码中的任何地方,也不会从您找到它们的地址加载。

mov di,0x0500
与BIOS查找的引导扇区签名没有连接,以查看驱动器是否包含可引导引导扇区。它不是
0x55
,它是
0x0500
si
di
被用作地址,而不是数据。@PeterCordes我当时一定有点糊涂了。从链接中,它说
这可以通过在实模式引导时将位于地址0000:7DFE的引导扇区标识符(0xAA55)与位于地址FFFF:7E0E的更高值1 MiB进行比较来实现。
那么引导签名与它有什么关系?我现在也注意到我用错误的方式得到了字节。第一部分是AA,第二部分是55。此外,您可能应该阅读此代码,以便了解此代码为什么会有用:
mov di,0x0500
与BIOS查找的引导扇区签名没有连接,以查看驱动器是否包含可引导引导扇区。它不是
0x55
,它是
0x0500
si
di
被用作地址,而不是数据。@PeterCordes我当时一定有点糊涂了。从链接中,它说
这可以通过在实模式引导时将位于地址0000:7DFE的引导扇区标识符(0xAA55)与位于地址FFFF:7E0E的更高值1 MiB进行比较来实现。
那么引导签名与它有什么关系?我现在也注意到我用错误的方式得到了字节。第一部分是AA,第二部分是55。你可能也应该读一下这段代码,这样你就知道为什么这段代码会有用了:那么从我所看到的(我可能错了),它是不是在检查某种内存溢出,因为你要写两个地方?或者这是由于段和偏移量造成的?这是由于CPU在实模式下如何计算地址。A20门的首要原因是地址总线上有更多的位,地址不像8086上那样环绕。A20门强制关闭
; The following code is public domain licensed

[bits 16]

; Function: check_a20
;
; Purpose: to check the status of the a20 line in a completely self-contained state-preserving way.
;          The function can be modified as necessary by removing push's at the beginning and their
;          respective pop's at the end if complete self-containment is not required.
;
; Returns: 0 in ax if the a20 line is disabled (memory wraps around)
;          1 in ax if the a20 line is enabled (memory does not wrap around)

check_a20:
    pushf                                  ;Backup the current flags onto the stack
                                           ;Backup the below registers onto the stack
    push ds                                ;|
    push es                                ;|
    push di                                ;|
    push si                                ;-----

    cli                                    ;Disable interupts

    xor ax, ax                             ; ax = 0
    mov es, ax                             ;es = ax

    not ax                                 ; ax = 0xFFFF
    mov ds, ax                             ; ds = ax

    mov di, 0x0500                         ;Boot signature part one (0x55)
    mov si, 0x0510                         ;Boot signature part two (0xAA)

    mov al, byte [es:di]                   ;al = value at AA:55
    push ax                                ;Backup ax register onto the stack

    mov al, byte [ds:si]                   ;al = value at 55:AA
    push ax                                ;Backup al onto the stack

    mov byte [es:di], 0x00                 ;Memory location AA:55 = 0
    mov byte [ds:si], 0xFF                 ;Memory location at 55:AA = 0xFF

    cmp byte [es:di], 0xFF                 ;Does value at AA:55 = 0xFF? If so, this means A20 is disabled

    pop ax                                 ;Restore saved ax register
    mov byte [ds:si], al                   ;Set 55:AA to al

    pop ax                                 ;Restore ax register
    mov byte [es:di], al                   ;set AA:55 to al

    mov ax, 0                              ;Return status of this function = 0 (Disabled)
    je check_a20__exit                     ;A20 is disabled. Go to check_a20__exit

    mov ax, 1                              ;Return status of this function = 1 (Enabled)

check_a20__exit:
                                           ;Backup registers
    pop si
    pop di
    pop es
    pop ds
    popf                                   ;Backup flags

    ret                                    ;Return