此时,用户可能想知道这个系统是否具有长模式能力,该模式由绿色中的CPUID表示。这是通过尝试在EFLAGS中切换位21来确定的。
5BD C6460004 mov [bp], RED Assume CPUID incapable
5C1 55 push bp
5C2 89E5 mov bp, sp
5C4 669C pushfd Preserve original state
5C6 669C pushfd
5C8 804EFA20 or [bp-6], 20H
5CC 669D popfd Set flag
5CE 669C pushfd Re-read it
5D0 58 pop ax
5D1 58 pop ax AX = High order bits
5D2 669D popfd Restore original flags
5D4 5D pop bp
5D5 0FBAE005 bt ax, 5 Is bit 21 on
5D9 7328 jnc 603 No if CY=0现在我们将测试CPU是否支持扩展函数。
5DB C6460006 mov [bp], BROWN
5DF 66B801000080 mov eax, 0x80000000 Ext Func supported?
5E5 6650 push eax
5E7 0FA2 cpuid
5E9 6659 pop ecx
5EB 6639C8 cmp eax, ecx
5EE 7613 jna 603 AX >= 80000001H
5F0 C646000E mov [bp], YELLOW
5F4 B001 mov al, 1 AX = Read feature bits
5F6 0FA2 cpuid
5F8 660FBAE21D bt edx, 29 Long Mode?
5FD 7304 jnc 603
5FF C6460002 mov [bp], GREEN用选定的颜色显示CPUID
603 31C9 xor cx, cx
605 89CB mov bx, cx
607 8A5E00 mov bl, [bp] Selected color
60A BA0706 mov dx, 607H Line 7 column 8
60D E818FF call 528最后,确定A20行的状态,目前只因为它工作,所以已经实现了快速A20门。
610 56 push si
611 1E push ds
612 06 push es
613 C6460002 mov [bp], GREEN
617 B90080 mov cx, 8000H Retry count
This sets up DS:SI = 560H Is volatile as not needed anymore
ES:DI = 100560H
61A 8CCE mov si, cs
61C C1E604 shl si, 4
61F 81C66000 add si, 60H Offset from CS
623 89F7 mov di, si
625 83C710 add di, 16
628 31C0 xor ax, ax
62A 8ED8 mov ds, ax
62C 48 dec ax
62D 8EC0 mov es, ax
62F 57 push di
630 56 push si
631 AD lodsw
632 F7D8 neg ax
634 AB stosw
635 3944FE cmp [si-2], ax If equal A20 is off
638 5E pop si
639 5F pop di
63A 0F858E00 jnz 6cc Bounce A20 already on做快速A20
63E C646000E mov [bp], YELLOW
642 E492 in al, 92H
644 0C02 or al, 2
646 E692 out 92H, al
648 49 dec cx
649 75E4 jnz 62f Execute test again
NOTE: There is 125 bytes reserved here for additional methods of
enabling A20.
6C8 C6460004 mov [bp], RED A20 enabling failed以三种颜色之一显示"A20“
6CC 07 pop es
6CD 1F pop ds
6CE 5E pop si
6CF 8A5E00 mov bl, [bp]
6D2 31C9 xor cx, cx
6D4 B21C mov dl, 0x1c
6D6 E84FFE call 528
6D9 EB25 jmp 700从这里到扇区的尽头是I2H (6DB)居住的地方,可以在这个职位的底部查看
发布于 2017-07-09 13:04:04
的顺序排列的
此时,用户可能想知道这个系统是否具有长模式能力,该模式由绿色中的CPUID表示。这是通过尝试切换EFLAGS中的第21位来确定的。
看到“这是由.”使这一段有点误导,因为它似乎长模式的能力是决定仅仅通过查看EFLAGS的21。您的代码在一个3步的过程中正确地完成了,但这不是读者立即看到的。时间较少的人可能已经放弃阅读了!
推动bp移动bp,sp ..。或者bp-6,20H ..。pop bp
您已经使用BP寄存器在堆叠数字中设置了一个位。这可以通过编写or [esp+2], 20H进行优化。虽然这个指令需要两个额外的字节(ASP前缀和SIB字节),但是您可以从删除push、mov和pop指令中获得4个字节。
这里有个交易。如果在类似的情况下,您需要在一行中操作几个叠加的值,那么使用BP的时间就会更短。
bt,5是jnc 603上的21位如果是CY=0
Bit 5生活在AL寄存器中。通过不使用双操作码指令BT,可以缩短测试,以确定它是开的还是关的。这里的最佳选择是Modr/m无字节指令test al, imm8。
test al, 20h
jz 603 ;Bit 21 is off5DF66B801000080 mov eax,0x80000000 Ext支持?
注意到转储和指令之间的不一致吗?如果您复制/粘贴了这段代码,那么反汇编程序就有问题,否则就是一个错误。
推送eax cpuid pop cmp eax,ecx jna 603 AX >= 80000001H mov bp,黄色mov al,1 AX =读取特征位cpuid bt edx,29长模式?jnc 603
使用指令mov al, 1,您可以避免编写更长的mov eax, 80000001H。非常容易理解,但是1字节的inc ax仍然会更短。
在这个代码片段中也隐藏着一些危险。谁说英特尔/AMD在未来的处理器迭代中不会返回EAX8,31中的非零值?今天已经有一些叶数没有被使用了。
push eax ;(1)
cpuid
xchg ecx, eax ;Result from CPUID
pop eax ;(1)
cmp ecx, eax
jna 603
mov [bp], YELLOW
inc ax
cpuid
bt edx, 29 Long Mode?
jnc 603通过精确地弹出80000000小时,您可以保证inc ax将产生所需的80000001h。
我使用xchg ecx, eax是因为它比mov ecx, eax短1字节。
mov bx,cx mov bl,bp选定颜色
由于第一条指令只想使BH寄存器为零,所以您可以通过以下方式减少1字节:
movzx bx, [bp] Selected color 推送硅-2,如果A20相等,则为pop
当我第一次看到使用字符串原语时,我希望看到要比较的地址范围,但您只处理一个单词。接下来的代码将使用较少的指令,并且会缩短几个字节。注意分段覆盖前缀的使用。
mov ax, [si]
neg ax
mov [es:di], ax
cmp [si], ax使用前面的代码,您还可以停止使用DI,然后再刮掉4个字节,因为您知道DI=SI+16:
mov ax, [si]
neg ax
mov [es:si+16], ax
cmp [si], ax关于这段代码的最后一点是关于neg的使用。零的否定也是零。这就是为什么这种测试经常使用not,它保证值被修改。但是,这不会影响您的代码,因为您已经选择了一个肯定不包含零的地址。但是选择一个固定的地址,比如。21h*4 (DOS不一定加载)将使SI的设置更短,甚至允许您根本不使用SI。
mov ax, [0084h]
not ax
mov [es:0084h+16], ax
cmp [0084h], ax61F 81C66000相加si,60H抵消CS
我不知道这里发生了什么,但是我认为编译器应该自动给出这个指令的符号扩展版本。字节83h,C6h,60h。
648 49 dec 649 75E4 jnz 62f再次执行测试
当然,这只是loop。短1字节。
6D4 B21C mov dl,0x1c
您没有初始化DH寄存器,因为您知道它在上面的代码中具有正确的值。这很好,但是考虑到设置它和使用它之间的分离,并且考虑到您所包含的注释,.
注意:这里为启用A20的其他方法保留了125个字节。
..。我想知道,当您准备好添加这些额外的方法时,您是否会记得保留DH?
https://codereview.stackexchange.com/questions/166916
复制相似问题