Assembly 16位x86汇编程序,使用8位内存存储的颜色变量将蓝色绘制到屏幕时遇到问题?

Assembly 16位x86汇编程序,使用8位内存存储的颜色变量将蓝色绘制到屏幕时遇到问题?,assembly,memory,nasm,dos,x86-16,Assembly,Memory,Nasm,Dos,X86 16,以下代码在Xubuntu 16.04上编译并运行良好,使用 bashshell中的这些命令 nasm blue.asm-fbin-oblue.com dosbox./blue.com-退出 我遇到的问题是在20号线上 mov-al,1;字节[蓝色] 如果我用这个来代替呢 mov al,字节[蓝色] 该程序在屏幕上绘制了一种勃艮第酒,而不是蓝色。它通常适用于使用1,这是此处8位调色板中的颜色代码 这是完整的代码,如果还有其他问题,请随时告诉我 org 00h bits 16 sec

以下代码在Xubuntu 16.04上编译并运行良好,使用 bashshell中的这些命令

nasm blue.asm-fbin-oblue.com

dosbox./blue.com-退出

我遇到的问题是在20号线上
mov-al,1;字节[蓝色]

如果我用这个来代替呢
mov al,字节[蓝色]

该程序在屏幕上绘制了一种勃艮第酒,而不是蓝色。它通常适用于使用1,这是此处8位调色板中的颜色代码

这是完整的代码,如果还有其他问题,请随时告诉我

org 00h
bits 16       

section .data             

    blue:    db       1  

section .text
MAIN:

AsyncKeyInput:      

    mov     al, 13h
    int     10h
    ; Segment a000h
    mov     ax, 0a000h
    mov     es, ax
    ; Offset 0
    xor     di, di
    mov     al, 1;byte [blue]
    ; Looplength (320*200)/2 = 7d00
    mov     cx, 7d00h

hplot:
    mov [ es: di], al       ;set pixel to colour
    inc di          ;move to next pixel
    loop hplot      

    mov     ah, 1          ;Get the State of the keyboard buffer
    int     16h            ;key press
    jz      AsyncKeyInput ;if not zero then exit the program 

    ;exit program
    mov eax, 1
    mov ebx, 0
    int 0x80
ret 

该问题的解决方案是为com程序将程序段前缀正确设置为
org 100h
。下面是更正后的代码

org 100h
bits 16       

section .data             

    blue:    db       1h     

section .text
MAIN:

AsyncKeyInput:      

    mov     al, 13h
    int     10h
    ; Segment a000h
    mov     ax, 0a000h
    mov     es, ax
    ; Offset 0
    xor     di, di
    xor     eax, eax
    mov     al, byte [blue]
    ; Looplength (320*200)/2 = 7d00
    mov     cx, 7d00h

hplot:
    mov [ es: di], al       ;set pixel to colour
    inc di          ;move to next pixel
    loop hplot      

    mov     ah, 1          ;Get the State of the keyboard buffer
    int     16h            ;key press
    jz      AsyncKeyInput ;if not zero then exit the program 

    ;text mode
    mov     ax, 0003h
    int     10h         
ret 

org 00
org 0x100
int0x80
是一个退出系统调用而不是DOS退出,COM程序应该只与
ret
一起工作,我认为它是
org00
,但这是默认的对吗?那就不用申报了?它应该是
0x100
?区别是什么,堆栈大小正确吗?DOS COM程序的偏移量为0x100。变量的所有偏移量都将相对于0x100,而不是0x00,我的更改为-是。100h或0x100当然是一样的。两者都是十六进制。如果将其设置为0,则
blue
等变量的所有偏移都将相对于0原点。对于.COM程序,当DOS加载它们时,它们实际上是在段中的偏移量0x100处启动的。0x00和0x100之间的字节是相同的。还有一个(大)问题。COM没有任何部分,这只是另一个小问题,以
mov al,13h
int 10h
开始代码不是设置13h gfx模式的正确方法。您还必须将
ah
设置为零(“设置gfx模式服务”),在dosbox下,您很幸运,在加载COM后,他们的DOS在
ah
中保留零。因此
mov ax,13h
是加载AH=0,AL=0x13的正确方法。(然后标签
AsyncKeyInput
可能放置不好,导致每次重新初始化gfx模式)。@Ped7g“COM没有任何部分,很简单,如果你每次都重新启用图形模式,然后将其绘制为蓝色,它就会闪烁。如果您没有设置
ah
,它将被设置为后面的
int16h
中的某个值,并且您正在调用
int10h
的随机服务,
al=13h
。。。出于某种原因,你很幸运,没有把某件东西称为真正的碰撞/破坏,所以它对你“有效”,但它根本不正确。如果不想闪烁,您需要更改主循环逻辑,可能只需设置一次图形模式。关于linux:在linux(AFAIK)下,没有简单的方法可以直接访问视频ram,最简单的方法之一可能是加载一些类似于SDL的库(可能选择具有最简单API的库),然后从ASM调用它,或者甚至创建简单的C++骨架来为ASM代码(初始化视频、控制器等)编写环境,在C/C++中封装任何OS/HW的数据,然后在纯ASM中执行纯算法,并编写到已经准备好的缓冲区中以生成GFX。