在 VGA 模式下写入视频内存 13h

Luk*_*sie 5 assembly

我正在使用 NASM 来学习 x86 汇编,在 linux 上的 qemu 中运行我的代码。我正在尝试在屏幕上绘制一个像素。

为什么是这样

mov     bx,0xA000 
mov byte [bx],0x0A
Run Code Online (Sandbox Code Playgroud)

似乎什么也没做,但是

mov     bx,0xA000 
mov     es,bx 
mov byte [es:di],0x0A
Run Code Online (Sandbox Code Playgroud)

能画一个像素吗?

第二个问题:为什么我必须使用 [es:di] 而不仅仅是 [es]?

Bre*_*dan 5

在实模式下,用于读写的地址由段和偏移量组成,实际读取或写入的地址计算为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(除非SPBP正在用于地址的偏移部分,这使得SS默认/隐含段,或其总是使用的指令获取CS)。这意味着mov [di],axmov [ds:di],ax.

偏移量部分始终是显式的,CPU 不支持(例如)“默认偏移量假定为 0x0000”。这意味着你不能这样做,mov [es],ax因为没有偏移量(也没有办法对指令进行编码),你必须做类似的事情mov [es:0x0000],ax