使用Open Watcom内联汇编从结构指针访问struct成员

时间:2016-10-31 03:51:52

标签: c assembly io inline-assembly 16-bit

我有一些代码可以写入和读取VGA的I / O端口。我试图在内联汇编程序中实现工作C代码功能。我正在使用Open Watcom 2.0并编译DOS 16bit。

要写入VGA上的调色板,我想出了这个。这不能正常工作。

编辑:setPaletteColor的代码并不完全准确。我已更新以反映实际代码。

void setPaletteColor (unsigned char index, rgbColor *p_color)
{
    _asm
    {
        ; tell VGA card we are going to update a palette register
        mov dx,PALETTE_MASK
        mov al,0xff
        out dx,al

        ; tell VGA which register we will be updating
        mov dx,PALETTE_REGISTER_WR
        mov al,index
        out dx,al

        ; update the color in the register at index
        mov dx,PALETTE_DATA
        mov al,*p_color
        out dx,al
        mov al,*p_color // this is actually *(p_color+1) but this actually gets the next structure not the next data member, so I left it out of the code I typed for my question.
        out dx,al
        mov al,*p_color // same here, actually is *(p_color+2)
        out dx,al
    }
}

为了阅读,我有这个。这也无法正常工作。

void getPaletteColor (unsigned char index, rgbColor *p_color)
{
    unsigned char *p_red = &p_color->red;
    unsigned char *p_green = &p_color->green;
    unsigned char *p_blue = &p_color->blue;
    _asm
    {
        ; tell VGA card we are going to read a palette register
        mov dx,PALETTE_MASK
        mov al,0xff
        out dx,al

        ; tell VGA which register we will be reading
        mov dx,PALETTE_REGISTER_RD
        mov al,index
        out dx,al

        ; read the data into the color struct at 'p_color'
        mov dx,PALETTE_DATA
        in  al,dx
        mov *p_red,al
        in  al,dx
        mov *p_green,al
        in  al,dx
        mov *p_blue,al
     }   
}

现在这里有纯C版本。

void setPaletteColor (unsigned char index, rgbColor *p_color)
{
    outp(PALETTE_MASK,0xff);
    outp(PALETTE_REGISTER_WR, index);
    outp(PALETTE_DATA,p_color->red);
    outp(PALETTE_DATA,p_color->green);
    outp(PALETTE_DATA,p_color->blue); 
}

阅读。

void getPaletteColor (unsigned char index, rgbColor *p_color)
{
    outp(PALETTE_MASK,0xff);
    outp(PALETTE_REGISTER_RD, index);
    p_color->red   = inp(PALETTE_DATA);
    p_color->green = inp(PALETTE_DATA);
    p_color->blue  = inp(PALETTE_DATA); 
}

注意:我不能使用'。'运算符也不是' - >'内联汇编中的运算符,因为编译器不支持它。

这是rgbColor结构的定义。

typedef struct rgbColorTag
{
    unsigned char red;
    unsigned char green;
    unsigned char blue;
} rgbColor;

1 个答案:

答案 0 :(得分:1)

一个好问题将描述它是如何运作的。只是说它"不起作用"让我觉得这是一个语法错误,因为我不知道Watcom风格的内联asm。我只是假设它类似于MSVC样式,并且在asm中使用C解除引用运算符是语法错误(例如在mov al,*p_color中)。

显然,这是Open Watcom的有效语法,但是您将加载相同的字节3次。也许尝试mov al, *(p_color+1)第二个字节?虽然那可能只是做C指针数学,并获得下一个结构的开始。查看编译器手册以获取可用的语法选项。

您也可以将指针加载到寄存器中并自己使用偏移量(使用mov al, [si+1]等寻址模式)。这取决于按顺序排列的3个结构成员没有填充,但我认为这应该是一个安全的假设。您可以随时检查编译器的asm输出,看看它是如何布局结构的。

由于您的结构以正确的顺序排列,您应该能够使用OUTS在其中循环3个字节。甚至REP OUTS,所以你不需要写一个循环。

    cld
    mov   si, p_color        ; get the function arg in a register
    mov   dx, PALETTE_DATA
    mov   cx, 3
    rep outsb                ; OUT 3 times, to port DX, using data from DS:[SI] (and do SI++ post-increment)

同样,对于阅读,

    cld
    mov   di, p_color
    mov   dx, PALETTE_DATA
    mov   cx, 3
    rep insb              ; IN 3 times, to port DX, using data from DS:[DI] (and do DI++)