2016-10-31 12 views
0

VGA에 대한 I/O 포트에 쓰고 읽는 코드가 있습니다. 인라인 어셈블러에서 작동하는 C 코드 기능을 구현하려고합니다. Open Watcom 2.0을 사용하고 DOS 16bit 용으로 컴파일하고 있습니다.struct 구조체에서 Open Watcom 인라인 어셈블리를 사용하여 구조체 멤버에 액세스

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; 
+0

도움이 http://bos.asmhackers.net/docs/vga_without_bios/docs/palettesetting.pdf합니까? 너와 똑같은 일을하는 것 같아. –

+0

* 참고 : '.'문자는 사용할 수 없습니다. 연산자 및 인라인 어셈블리의 '->'연산자는 컴파일러에서 지원하지 않으므로 * C의 로컬 변수에 데이터를 할당하고 인라인 asm에서 읽거나 씁니다. 그것은 컴파일러가 실제로 스택에 복사하기위한 추가 명령어를 내 보낸 것처럼 바보 같이 처리 할 수도 있습니다. 순수한 C 버전의 문제점은 무엇입니까? 컴파일러가 느린 코드를 생성합니까?인라인 asm으로 직접 코드를 수행하는 것이 더 빠른 코드를 얻을 수 있다고 생각하는 이유는 무엇입니까? 또는'outp'는 내장 함수가 아니라 실제 함수라고 불립니다. –

+1

@PeterCordes 내 어셈블리 "getPaletteColor()"를 보겠습니다. 로컬 포인터 변수를 사용하여 색상 구조체에 대한 멤버의 오프셋을 가져옵니다. 순수한 C 버전은 괜찮지 만이 모든 작업을 수행하는 방법을 알고 싶습니다. 이것이 내가 DOS 프로그램을 작성한 이유입니다. 이것은 모두 학습 경험이며, 지금까지 많이 배웠습니다. 'outp '는 I/O 포트에 쓰기 위해 컴파일러와 함께 제공되는 함수입니다. 'inp'와 동일합니다. – SeanRamey

답변

1

좋은 질문은 어떻게 작동하지 않는지 설명했을 것입니다. 그냥 "작동하지 않는다"고 말하면서 Watcom 스타일 인라인 asm을 모르기 때문에 문법 오류라고 가정합니다. 방금 MSVC 스타일과 유사하다고 가정하고 asm에서 C 역 참조 연산자를 사용하는 것은 구문 오류입니다 (예 : mov al,*p_color).

분명히 Open Watcom의 유효한 구문이지만 은 동일한 바이트를 3 번로드합니다.입니다. 어쩌면 두 번째 바이트로 mov al, *(p_color+1)을 시도해보십시오. 그게 그냥 C 포인터 수학을 할 수도 있지만 다음 구조체의 시작 부분을 얻을 수 있습니다. 사용 가능한 구문 옵션에 대해서는 컴파일러 설명서를 확인하십시오.


또한 단지 레지스터에 포인터를로드 (mov al, [si+1] 같은 주소 모드로) 그것으로부터 자신을 오프셋 (offset)를 사용할 수 있습니다. 이것은 패딩없이 순서대로 배열되는 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++) 
+0

사실, 내 코드는 오류나 경고없이 컴파일되고 실행됩니다. 그것은 단지 내가 기대했던 것을하지 않습니다. 이 코드를 가져 주셔서 감사합니다. 나는 그것을 적응시키고 그것이 효과가 있는지보기 위해 노력할 것이다! :) – SeanRamey

+0

@SeanRamey : 아, 그래, Watcom inline-asm이 MSVC와 다른 것 같아. 이것은 단지 asm을 배움으로써 16 비트 코드 외부에서 쓸모가없는 툴과 구문을 배우는 시간을 소비한다는 것을 의미하므로, 현대 C++의 asm 출력을 보는데 도움이되지는 않을 것이라는 점을 강조한다. 성능 카운터 프로필을보고 코드를 작성하고 2016 년에 asm을 알아두면 유용합니다. –

+0

좋습니다. 그래서 시도해 보았습니다. 그것은 실행되지만 이전과 거의 똑같은 일을합니다. 쓰지 말아야 할 몇 개의 무작위 픽셀을 작성하는 엄청난 이상한 부작용이 있습니다. 또한, 실제로 이것은 현대 C 코드에서 asm을 사용하여 상당히 도움이됩니다. 여분의 헛소리를 모두 없애면 더 명확하게 볼 수 있습니다. 나는 또한이 물건의 역사적인 부분을 너무 좋아한다. 그리고 실제 하드웨어에 대한 엄청난 양을 배웁니다. 나는이 이상한 상황에 빠지기 때문에 내가 배운다. 나는 그들을 알아낼 때까지 분명히 뭔가를 배웠다. – SeanRamey