我正在使用NASM学习x86汇编,在linux上的qemu中运行我的代码。我正试图在屏幕上画一个像素。
为什么
mov bx,0xA000
mov byte [bx],0x0A
似乎什么都没做,但
mov bx,0xA000
mov es,bx
mov byte [es:di],0x0A
能画一个像素吗?
第二个问题:为什么我必须使用[es:di]而不仅仅是[es]?
在实际模式中,用于读取和写入的地址由一个段和一个偏移量组成,从中读取或写入的实际地址计算为segment * 16 + offset
。
注意:在文档等中;段和偏移量通常是由冒号连接的2个数字(如0x1234:0x5678,其中0x1234是段,0x5678是偏移量)。
对于0x0000:0xA000,实际地址为0x0000A000。该地址通常对应于RAM。
对于0xA000:0x0000,实际地址为0x000A0000。这就是传统VGA显示存储区的位置(当视频卡模拟古代VGA的320*200视频模式时使用)。
所有读取和写入都使用一个段寄存器,如果您没有明确指定一个(例如mov [es:di],ax
),则CPU使用默认/隐含段寄存器,通常为DS
(除非SP
或BP
用于使SS
成为默认/隐含分段的地址偏移部分,或其始终使用CS
的指令提取)。这意味着mov [di],ax
的作用与mov [ds:di],ax
的作用相同。
偏移部分总是显式的,CPU不支持(例如)"默认偏移为0x0000"。这意味着您不能执行mov [es],ax
,因为没有偏移量(也没有方法对指令进行编码),您必须执行类似mov [es:0x0000],ax
的操作。