Turbo C使用的汇编函数 -- VGA 12H模式图形函数(一)

        上次整理以前DOS下的代码,找了个线性回归分析函数,觉得可能还有用,于是放在了《C语言版的线性回归分析函数》中,今天在CSDN的C/C++版,发现居然还有人求DOS下VGA 12H模式下的直接写屏代码,临时找了2个以前的文件,发了出去供参考。后来仔细找了一会,把以前DOS下写的供Trubo C使用的VGA 12H直接写屏图形函数找齐了,还有鼠标和XMS内存管理函数,决定放在这里,供C语言初学者参考。因为这些函数全部都是外部汇编代码文件,比较长,只得分几篇文章存放,由于时间太长,有些代码我自己现在也说不清楚,除个别情况外,本人不对代码作解释,纯粹代码粘贴。这篇文章中存放VGA 12H图形的基本函数和C调用头文件以及全部汇编函数的MAKEFILE。

        有人可能说,Turbo C不是有图形库吗,为啥还要自己写图形库?因为Trubo C自带的图形库通用性太强,导致当时DOS下使用它时,速度很慢,所以我写了供自己用的专用VGA图形库,没有考虑通用性,故而速度相当快,现在的机器速度快,使用Trubo C的图形库当然没有慢的感觉了,不过,我认为这些代码对C初学者来说,还是有价值的:首先可以了解VGA12H模式下的直接写屏技术;其次可以掌握C语言与外部汇编函数的相互调用方式;再次,本图形库中很多函数中包含了一些现在的计算机书中很少有的基础图形算法,如任意直线、圆、弧、图形填充等整数算法

        首先给出全部汇编文件的MAKEFILE,该文件名graph.mak:

###############################################################
#  FileName:  graph.mak                                                                                                    #
###############################################################
TLIB     =  TLib
TASM    
=  Tasm  / ml
#
! if   ! $d(MDL)
MDL        
=  s
! endif
#
! if  $(MDL)  ==  t
TasmComm    
=   / D__TINY__
! elif $(MDL)  ==  s
TasmComm    
=   / D__SMALL__
! elif $(MDL)  ==  m
TasmComm    
=   / D__MEDIUM__
! elif $(MDL)  ==  c
TasmComm    
=   / D__COMPACT__
! elif $(MDL)  ==  l
TasmComm    
=   / D__LARGE__
! endif
#
#
Dep_graph    
=  graph$(MDL).lib
#
Dep_graphdlib 
=  
   xms.asm
   mouse.asm
   grroll.asm
   grputch.asm
   grimage.asm
   grfill.asm
   grellip.asm
   grbase.asm
   grarc.asm
   graph.inc
   tasm_c.inc

$(Dep_graph) : $(Dep_graphdlib)
  del $(Dep_graph)
  $(TASM) $(TasmComm) xms.asm
  $(TASM) $(TasmComm) mouse.asm
  $(TASM) $(TasmComm) grroll.asm
  $(TASM) $(TasmComm) grputch.asm
  $(TASM) $(TasmComm) grimage.asm
  $(TASM) $(TasmComm) grfill.asm
  $(TASM) $(TasmComm) grellip.asm
  $(TASM) $(TasmComm) grbase.asm
  $(TASM) $(TasmComm) grarc.asm
  $(TLIB) $(Dep_graph)
+ xms.obj + mouse.obj + grroll.obj + grputch.obj
   
+ grimage.obj + grfill.obj + grellip.obj + grbase.obj + grarc.obj
  del 
* .obj

        在命令行使用Turbo C的make.exe,可以制造一个TC库文件GraphX.lib,其中X为存储模式,由make命令行的MDL宏指定(缺省为small模式),如制造一个中模式库,命令行为(注:由于10多年没用过这种东西,我的记忆不知道是否正确,如果错误,请原谅):

        make -DMDL=m -fgraph.mak

        然后给出TC调用的图形汇编函数的头文件,从这个头文件可以看出,在DOS下,不仅TC调用它们,也可供Turbo C++或者Borland C++调用本文的这些函数。需要说明的是,从InitUCDOS开始的函数已经不完全是纯图形函数了,而是与UCDOS有关的字符串显示函数,如果不使用UCDOS,可以将它们以及后面的代码删掉;另外,PutBmp函数只是用来显示16色未压缩过的位图文件的图形数据,没有打开文件功能,本文最后贴出以前的一个测试程序代码

/*   GRAPH.H   */

#ifndef    __GRAPH_H
#define     __GRAPH_H

#ifdef    __cplusplus
extern   " C "  {
#endif

/*  打开图形屏幕  */
void  OpenGraph(  void  );
/*  以正文方式关闭图形屏幕  */
void  CloseGraph(  void  );
/*  设置图形操作边界, 参数: 左上角 X, Y 坐标, 右下角 X, Y 坐标;
   除图像保存, 移动函数外, 所有图形均进行裁剪 
*/
void  SetBorder( int int int int );
/*  使用缺省的屏幕尺寸为图形边界  */
void  DefBorder( void );
/*  设置当前作图颜色值为 Value, 返回当前的值  */
int  SetColor(  int  Value );
/*  返回当前颜色值  */
int  GetColor();
/*  置写图型屏幕方式(0 - 3), 返回当前的方式  */
int  SetDrMode(  int  Mode );
/*  在(X, Y)用当前色写点  */
void  PutPixel( int  X,  int  Y);
/*  返回(X, Y)的颜色值  */
int  GetPixel( int  X,  int  Y);
/*  从(X1, Y1)至(X2, Y2)画直线  */
void  Line( int  X1,  int  Y1,  int  X2,  int  Y2);
/*  从(X1, Y1)至(X2, Y2)画填充矩形(无边界线)  */
void  Bar( int  X1,  int  Y1,  int  X2,  int  Y2);
/*  用颜色从(X1, Y1)至(X2, Y2)画矩形  */
void  Rectangle( int  X1,  int  Y1,  int  X2,  int  Y2);
/*  保存(Left, Top)至(Right, Bottom)内的图象到 Buf 中  */
unsigned GetImage(
int  Left,  int  Top,  int  Right,  int  Bottom,  void  far  * Buf);
/*  将 Buf 内保存的图象在(Row, Col)处显示, Mode 显示方式(0 - 3)  */
void  PutImage( int  Row,  int  Col,  void  far  * Buf,  int  Mode);
/*  计算并返回保存(Left, Top)至(Right, Bottom)内的图象缓冲区的字节数  */
long  ImageSize( int  Left,  int  Top,  int  Right,  int  Bottom);
/*  将屏幕区(Left, Top)至(Right, Bottom)垂直移动 N 线, N 上移, -N 下移  */
void  Roll( int  n,  int  Left,  int  Top,  int  Right,  int  Bottom);
/*  安装用户掩膜 LnStyle 返回当前的线型  */
int  SetLnStyle( int  Lnstyle);
/*  安装用户图案 Pattern 及颜色 Color  */
void  SetPattern( void  far  * Pattern,  int  Color);
/*  以(X, Y)为园心, Radius 为半径画园  */
void  Circle( int  X,  int  Y,  int  Radius);
/*  以(X, Y)为园心, RadiusX 为 X 半径, RadiusY 为 Y 半径画椭园  */
void  Ellipse( int  X,  int  Y,  int  Radiusx,  int  Radiusy);
/*  以(X, Y)为园心, Radius 为半径, Start 为起始角, End为结束角画园弧  */
void  Arc( int  X,  int  Y,  int  Start,  int  End,  int  Radius);
/*  以(X, Y)为园心, Radius 为半径, Start 为起始角, End为结束角画扇形(不填充)  */
void  Slice( int  X,  int  Y,  int  Start,  int  End,  int  Radius);
/*  以(X, Y)为园心, Radius 为半径, Start 为起始角, End为结束角画馅饼形(不填充)  */
void  Pie( int  X,  int  Y,  int  Start,  int  End,  int  Radius);
/*  以(X, Y)为内点, Color 为填充色, 以当前图案进行区域填充  */
void  Fill( int  X,  int  Y,  int  Color);
/*  改变系统的颜色, Index 调色板号(0-15), Red 红色值, Green 绿色值, Blus 蓝色值
   颜色值范围为 0-63 
*/
void  SetPalette( int  Index,  int  Red,  int  Green,  int  Blus);
/*  从(X, Y)开始显示位图数据 Bmp  */
void  PutBmp( int  X,  int  Y,  void  far  * Bmp);
/*  定义字符显示和光标函数  */

/*  判断UCDOS是否启动, 已启动, 关闭UCDOS光标, 重新安装闪烁光标并返回 -1,
   否则返回 0, 参数为光标颜色值, 用此值与屏幕异或成实际光标颜色 
*/
int  InitUCDOS( int );
/*  撤消自安装的闪烁光标, 如果flag = 0恢复UCDOS光标  */
void  RestUCDOS( int  flag);
/*  显示光标  */
void  ShowCursor( void );
/*  隐蔽光标, 如多次隐蔽后, 需多次调用 ShowCursor()  */
void  HideCursor( void );
/*  设置字符坐标点的左上角坐标, 参数: X 坐标, Y 坐标  */
void  SetPos( int int );
/*  返回当前光标处字符的左上角坐标, 参数: X 坐标指针, Y 坐标指针  */
void  GetPos( int   * int   * );
/*  设置光标状态为插入方式(8*8光标, 缺省)或改写方式(8*4光标), 分别返回 1 或 0  */
int  InsertMode( void );
/*  在当前坐标写字符, 参数: 字符, 字符个数, 字符属性(高4位背景色,低4位前景色);
   字符为 16*16 点阵, 显示字符后, 不改变坐标 
*/
void  Putch( int int int );
/*  在给定的坐标处显示字符串, 坐标超长或遇结束符 0 中止, 返回实际写的字符数,
   参数: X 起始坐标, Y 坐标, 字符串, X 结束坐标, 字符属性; 显示后坐标在字符串尾 
*/
int  Putss( int int char   * int int );

#ifdef    __cplusplus
}
#endif

#endif

         下面是TC外部汇编(TASM)函数通用的插入文件,该文件定义了一些与存储模式有关的宏,包含它的汇编文件可以用TASM.EXE编译成TC的任意模式obj文件:

; TASM_C.INC

IFNDEF __TINY__
    IFNDEF __SMALL__
    IFNDEF __MEDIUM__
        IFNDEF __COMPACT__
        IFNDEF __LARGE__
            DISPLAY  
" **Warning** You must supply a model symbol. "
            __SMALL__    equ    
1
        ENDIF
        ENDIF
    ENDIF
    ENDIF
ENDIF

    IDEAL

IFDEF    __TINY__
    LPROG        equ    
0
    LDATA        equ    
0
    MODEL        TINY, PROLOG
ENDIF

IFDEF    __SMALL__
    LPROG        equ    
0
    LDATA        equ    
0
    MODEL        SMALL, PROLOG
ENDIF

IFDEF    __MEDIUM__
    LPROG        equ    
1
    LDATA        equ    
0
    MODEL        MEDIUM, PROLOG
ENDIF

IFDEF    __COMPACT__
    LPROG        equ    
0
    LDATA        equ    
1
    MODEL        COMPACT, PROLOG
ENDIF

IFDEF    __LARGE__
    LPROG        equ    
1
    LDATA        equ    
1
    MODEL        LARGE, PROLOG
ENDIF

IF LDATA
    DPTR_    EQU    dword
    DS_    EQU    ds:
    ES_    EQU    es:

    MACRO    LDS_    Register, Memory
        lds    Register, Memory
    ENDM    LDS_

    MACRO    LES_    Register, Memory
        les    Register, Memory
    ENDM    LES_

    MACRO    PUSHDS_
        push    ds
    ENDM    PUSHDS_

    MACRO    POPDS_
        pop    ds
    ENDM    POPDS_

    MACRO    PUSHES_
        push    es
    ENDM    PUSHES_

    MACRO    POPES_
        pop    es
    ENDM    POPES_
ELSE
    DPTR_    EQU    word
    DS_    EQU
    ES_    EQU

    MACRO    LDS_    Register, Memory
        mov    Register, Memory
    ENDM    LDS_

    MACRO    LES_    Register, Memory
        mov    Register, Memory
    ENDM    LES_

    MACRO    PUSHDS_
    ENDM    PUSHDS_

    MACRO    POPDS_
    ENDM    POPDS_

    MACRO    PUSHES_
    ENDM    PUSHES_

    MACRO    POPES_
    ENDM    POPES_
ENDIF

; TASM_C.INC END

        基本图形文件,该文件提供了几个基本的图形函数(带下划线的函数)和其它图形汇编文件使用的内部函数(没有下划线的函数,C不能直接调用):

; graphbas.asm    (VGA  16  色  640   *   480  方式)

    P386N
    include    tasm_c.inc

MAXCOLOR    equ    
15         ; 最大颜色值
MAXX        equ    
639         ; 最大 X 象素
MAXY        equ    
479         ; 最大 Y 象素
DSPMEMSEG    equ    0A000h        ; 屏显起始地址
DMWIDTH        equ    
80         ; 屏幕每线字节数
GRMODE        equ    12h        ; 屏显方式

    DATASEG

    PUBLIC    Color
    PUBLIC    DrMode
    PUBLIC    MinX
    PUBLIC    MinY
    PUBLIC    MaxX
    PUBLIC  MaxY
    PUBLIC    WidthX
    PUBLIC    WidthY

Color        dw    
7
DrMode        dw    
3
LnStyle        dw    0ffffh
Pattern        db    
8  dup (0ffh)
MinX        dw    
0
MinY        dw    
0
MaxX        dw    MAXX
MaxY        dw    MAXY
WidthX        dw      MAXX
WidthY        dw    MAXY

    CODESEG

    PUBLIC    _OpenGraph
    PUBLIC    _CloseGraph
    PUBLIC    _Line
    PUBLIC    _PutPixel
    PUBLIC    _GetPixel
    PUBLIC    _SetColor
    PUBLIC    _GetColor
    PUBLIC    _SetDrMode
    PUBLIC    _SetLnStyle
    PUBLIC    _SetPattern
    PUBLIC    _Rectangle
    PUBLIC    _Bar
    PUBLIC    _SetPalette
    PUBLIC    _SetBorder
    PUBLIC    _DefBorder
    PUBLIC    GetDspMem
    PUBLIC    GetDspMemOff
    PUBLIC    SetWrMode
    PUBLIC    SetWrMode0
    PUBLIC  RestReg
    PUBLIC    RestReg0
    PUBLIC    TestPoint
    PUBLIC    Bar
    PUBLIC    GetPixel
    PUBLIC    PutPixel
;
; GetDspMem; ax 
=  X, bx  =  Y,  return  es:bx  =  DspMem
;
PROC    GetDspMem
    push    DSPMEMSEG
    pop    es
ENDP
;
PROC    GetDspMemOff
    push    ax
    shl    bx, 
4
    mov    ax, bx        ; bx 
=  Y  *   16
    shl    ax, 
2
    add    bx, ax        ; ( bx 
+=  ( Y  *   64  )) or ( bx  =  Y  *   80  )
    pop    ax
    shr    ax, 
3         ; ax  =  X  /   8
    add    bx, ax        ; 
return  BX  =  ( Y  *   80   +  X  /   8  )
    ret
ENDP
;
PROC    SetWrMode0
    xor    al, al
    mov    ah, [
byte  Color]
    mov    dx, 3ceh
    
out     dx, ax
    mov    ax, 0f01h
    
out     dx, ax
    xor    ah, ah
ENDP
;
; SetWrMode, ah 
=  Mode( 0   -   3 );  return  dx  =  3cfh
;
PROC    SetWrMode
      mov    al, 
5
      mov    dx, 3ceh
      
out     dx, ax
    mov    ax, [DrMode]
      
out     dx, ax
      mov    al, 
8
    
out     dx, al
    inc    dx
    ret
ENDP
;
PROC    RestReg0
      mov    dx, 3ceh
      xor    ax, ax
      
out     dx, ax
      inc    ax
    
out     dx, ax
ENDP
;
PROC    RestReg
      mov    dx, 3ceh
      mov    ax, 0ff08h
      
out     dx, ax
      mov    ax, 
5
      
out     dx, ax
      mov    ax, 
3
      
out     dx, ax
    ret
ENDP
;
; TestPoint; ax 
=  x1, bx  =  y1, si  =  x2, di  =  y2, cx  =  WintdX, dx  =  WidthY
;
PROC    TestPoint

    cmp    ax, si
    jle    @@
1
    xchg    ax, si
@@
1 :
    cmp    bx, di
    jle    @@
2
    xchg    bx, di
@@
2 :
    or    di, di
    js    @@
7
    cmp    di, dx
    jle    @@
3
    mov    di, dx
@@
3 :
    or    si, si
    js    @@
7
    cmp    si, cx
    jle    @@
4
    mov    si, cx
@@
4 :
    cmp    bx, dx
    jg    @@
7
    or    bx, bx
    jns    @@
5
    xor    bx, bx
@@
5 :
    cmp    ax, cx
    jg    @@
7
    or    ax, ax
    jns    @@
6
    xor    ax, ax
@@
6 :
    clc
    ret
@@
7 :
    stc
    ret
ENDP
;
void  _SetBorder(  int  X1,  int  Y1,  int  X2,  int  Y2 )
;
PROC    _SetBorder

    ARG    X1 : word, Y1 : word, X2 : word, Y2 : word

    mov    ax, [X1]
    mov    bx, [X2]
    cmp    ax, bx
    jle    @@
1
    xchg    ax, bx
@@
1 :
    or    ax, ax
    jns    @@
2
    xor    ax, ax
    or    bx, bx
    jns    @@
2
    xor    ax, ax
@@
2 :
    cmp    bx, MAXX
    jle    @@
3
    mov    bx, MAXX
    cmp    ax, MAXX
    jle    @@
3
    mov    ax, MAXX
@@
3 :
    mov    [MinX], ax
    mov    [MaxX], bx
    sub    bx, ax
    mov    [WidthX], bx
;
    mov    ax, [Y1]
    mov    bx, [Y2]
    cmp    ax, bx
    jle    @@
4
    xchg    ax, bx
@@
4 :
    or    ax, ax
    jns    @@
5
    xor    ax, ax
    or    bx, bx
    jns    @@
5
    xor    ax, ax
@@
5 :
    cmp    bx, MAXY
    jle    @@
6
    mov    bx, MAXY
    cmp    ax, MAXY
    jle    @@
6
    mov    ax, MAXY
@@
6 :
    mov    [MinY], ax
    mov    [MaxY], bx
    sub    bx, ax
    mov    [WidthY], bx
    ret
ENDP
;
PROC    _DefBorder

    mov    [word MinX], 
0
    mov    [word MinY], 
0
    mov    [word MaxX], MAXX
    mov    [word MaxY], MAXY
    mov    [word WidthX], MAXX
    mov    [word WidthY], MAXY
    ret
ENDP
;
;
void  OpenGraph()
;
PROC    _OpenGraph

    mov    ax, GRMODE
      
int     10h
      mov    dx, 3c4h
      mov    ax, 0f02h
    
out     dx, ax
    call    RestReg0
    call    _DefBorder
    ret
ENDP
;
;
void  CloseGraph()
;
PROC    _CloseGraph

      mov    ax, 
3
    
int     10h
    ret
ENDP
;
int  SetColor(  int  Color )
;
PROC    _SetColor

    ARG    color : word

    mov    ax, [color]
    and    ax, MAXCOLOR
    xchg    ax, [Color]
    ret
ENDP
;
int  SetDrMode(  int  Mode )
;
PROC    _SetDrMode

    ARG    mode : word

    mov    ax, [mode]
    and    ax, 
3
    shl    ax, 
11
    or    ax, 
3
    xchg    ax, [DrMode]
    shr    ax, 
11
    ret
ENDP
;
int  SetLnStyle(  int  linestyle )
;
PROC    _SetLnStyle

    ARG    linestyle : word
    mov    ax, [linestyle]
    xchg    ax, [LnStyle]
    ret
ENDP
;
void  SetPattern(  void  far  * Pat,  int  color )
;
PROC    _SetPattern

    ARG    pat : far ptr, color : word
    USES    di, si, ds

    push    [word color]
    call    _SetColor
    pop    ax
    push    ds
    pop    es
    lea    di, [Pattern]
    lds    si, [dword pat]
    mov    cx, 
8
    cld
    rep    movsb
    ret
ENDP
;
int  GetColor(  void  )
;
PROC    _GetColor

    mov    ax, [Color]
    ret
ENDP
;
; ax 
=  x, bx  =  y, dx  =  03cfh
;
PROC    PutPixel

    cmp    ax, [WidthX]
    ja    @@
1
    cmp    bx, [WidthY]
    ja    @@
1
    add    ax, [MinX]
    add    bx, [MinY]
    push    ax
    call    GetDspMem
    pop    cx
    and    cx, 
7
    mov    al, 80h
    shr    al, cl
    
out     dx, al
    mov    ax, [Color]
    xchg    al, [
byte  es:bx]
@@
1 :
    ret
ENDP
;
void  PutPixel(  int  x,  int  y )
;
PROC    _PutPixel

    ARG    x : word, y : word

    mov    ah, 
2
    call    SetWrMode
    mov    ax, [x]
    mov    bx, [y]
    call    PutPixel
    call    RestReg
    ret
ENDP
;
; ax 
=  x, bx  =  y
;
PROC    GetPixel

    push    ax
    call    GetDspMem
    pop    cx
    not    cl
    and    cl, 
7
    xor    ch, ch
    mov    dx, 3ceh
    mov    al, 
4
    
out     dx, al
    inc    dx
    mov    al, 
3
@@
1 :
    
out     dx, al
    mov    ah, [
byte  es:bx]
    shr    ah, cl
    and    ah, 
1
    shl    ch, 
1
    or    ch, ah
    dec    al
    jns    @@
1
    mov    al, ch
    cbw
    ret
ENDP
;
int  GetPixel(  int  x,  int  y )
;
PROC    _GetPixel

    ARG    x : word, y : word

    mov    ax, [x]
    mov    bx, [y]
    add    ax, [MinX]
    add    bx, [MinY]
    call    GetPixel
    ret
ENDP
;
;    (b2 
-  b1)  *  (w  -  a1)  /  (a2  -  a1));
;    ax 
=  w, cx  =  a1, bx  =  b1, si  =  a2, di  =  b2
;
PROC    SumXY

    push    bx
    push    dx
    push    ax
    mov    ax, di
    sub    ax, bx
    pop    bx
    sub    bx, cx
    imul    bx
    mov    bx, si
    sub    bx, cx
    idiv    bx
    pop    dx
    pop    bx
    ret
ENDP
   ; cx 
=  x, bx  =  y; ret ax  =  Code
   ;
PROC    OutCode

    xor    ax, ax
    or    cx, cx
    jns    @@
1
    or    ax, 0001b
@@
1 :
    or    bx, bx
    jns    @@
2
    or    ax, 0010b
@@
2 :
    cmp    cx, [WidthX]
    jle    @@
3
    or    ax, 0100b
@@
3 :
    cmp    bx, [WidthY]
    jle    @@
4
    or    ax, 1000b
@@
4 :
    ret
ENDP
;
PROC    _Line

    ARG    x1 : word, y1 : word, x2 : word, y2 : word
    USES    si, di

    mov    cx, [x2]
    mov    bx, [y2]
    call    OutCode
    mov    dh, al      ; dh 
=  p2
    mov    si, cx
    mov    di, bx
    mov    cx, [x1]
    mov    bx, [y1]
@@
1 :
    call    OutCode
    mov    dl, al        ; dl 
=  al  =  p1
    test    al, dh        ; 
if ((p1  &  p2))  return
    jz    @@
2
    jmp    @@
17
@@
2 :
    or    al, dh        ; 
if ( ! (p1  |  p2) line
    jz    @@
7

    cmp    dl, 
0         ;  if ( ! p1) x1 swap x2; y1 swap y2; p1 swap p2
    jne    @@
3
    xchg    cx, si
    xchg    bx, di
    xchg    dh, dl
@@
3 :
    test    dl, 0001b
    jz    @@
4
    xor    ax, ax        ; 
if (x1  <   0 )
    call    SumXY
    add    bx, ax        ; y1 
+=  (y2  -  y1)  *  ( - x1)  /  (x2  -  x1)
    xor    cx, cx        ; x1 
=   0
    jmp     
short  @@ 1
@@
4 :
    test    dl, 0010b
    jz    @@
5
    xor    ax, ax          ; 
if (y1  <   0 )
    xchg    cx, bx
    xchg    si, di
    call    SumXY
    xchg    cx, bx
    xchg    si, di
    add    cx, ax        ; x1 
+=  (x2  -  x1)  *  ( - y1)  /  (y2  -  y1)
    xor    bx, bx        ; y1 
=   0
    jmp    
short  @@ 1
@@
5 :
    test    dl, 0100b
    jz    @@
6
    mov    ax, [WidthX]    ; 
if (x1  >  WidthX)
    call    SumXY
    add    bx, ax        ; y1 
+=  (y2  -  y1)  *  (WidthX  -  x1)  /  (x2  -  x1)
    mov    cx, [WidthX]    ; x1 
=  WidthX
    jmp    @@
1
@@
6 :
    test    dl, 1000b
    jz    @@
1
    mov    ax, [WidthY]    ; 
if (y1  >  WidthY)
    xchg    cx, bx
    xchg    si, di
    call    SumXY
    xchg    cx, bx
    xchg    si, di
    add    cx, ax        ; x1 
+=  (x2  -  x1)  *  (WidthY  -  y1)  /  (y2  -  y1)
    mov    bx, [WidthY]    ; y1 
=  WidthY
    jmp    @@
1
@@
7 :
    mov    ax, cx        ; line(x1, y1, x2, y2)
    add    ax, [MinX]
    add    bx, [MinY]
    add    si, [MinX]
    add    di, [MinY]
    mov    [word y1], 
80
    mov    [word x1], 
0
    cmp    ax, si
    jle    @@
8
    xchg    ax, si
    xchg    bx, di
@@
8 :
    sub     si, ax
    sub    di, bx
    jge    @@
9
    neg    [word y1]
    neg    di
@@
9 :
    cmp    di, si
    jle    @@
10
    mov    [word x1], 
1
    xchg    di, si
@@
10 :
    push    si
    mov    [y2], di
    mov    [x2], si
    mov    di, si
    shr    di, 
1

    push    ax
    call    GetDspMem
    mov    ah, 
2
    call    SetWrMode
    mov    si, [LnStyle]
    pop    cx
    and    cl, 
7
    mov    al, 80h
    shr    al, cl
    
out     dx, al
    mov    ah, [
byte  Color]
    pop    cx
    inc    cx
@@
11 :
    test    si, 8000h
    jz    @@
12
    push    ax
    xchg    [
byte  es:bx], ah
    pop    ax
@@
12 :
    rol    si, 
1
    add    di, [y2]
    cmp    di, [word x2]
    jle    @@
13
    add    bx, [y1]
    sub    di, [x2]
    jmp    
short  @@ 14
@@
13 :
    cmp    [word x1], 
0
    je    @@
14
    add    bx, [y1]
    loop    @@
11
    jmp    
short  @@ 16
@@
14 :
    ror    al, 
1
    test    al, 80h
    jz    @@
15
    inc    bx
@@
15 :
    
out     dx, al
    loop    @@
11
@@
16 :
    call    RestReg
@@
17 :
    ret
ENDP
;
void  Rectangle(  int  x1,  int  y1,  int  x2,  int  y2 )
;
PROC    _Rectangle

    ARG    x1 : word, y1 : word, x2 : word, y2 : word
    USES    si, di

    mov    si, [x1]
    mov    di, [y1]
    push    di
    push    [word x2]
    push    di
    push    si
    call    _Line
    add    sp, 
8
    inc    di
    push    [word y2]
    push    [word x2]
    push    di
    push    [word x2]
    call    _Line
    add    sp, 
8
    push    [word y2]
    push    [word x2]
    push    [word y2]
    push    si
    call    _Line
    add    sp, 
8
    dec    [word y2]
    push    [word y2]
    push    si
    push    di
    push    si
    call    _Line
    add    sp, 
8
    ret
ENDP
;
; ax 
=  x1, bx  =  y1, si  =  x2, di  =  y2
;
PROC    Bar
    push    bp
    sub    di, bx
    inc    di
    push    di
    push    bx
    push    ax
    call    GetDspMem
    mov    di, bx
    pop    ax
    mov    cx, ax
    mov    bx, 0ffffh
    and    cl, 
7
    shr    bh, cl
    mov    cx, si
    not    cl
    and    cl, 
7
    shl    bl, cl
    shr    ax, 
3
    shr    si, 
3
    sub    si, ax
    mov    bp, si
    pop    si
    pop    cx
    cld
@@
1 :
    push    cx
    push    di
    push    si
    push    ds
    and    si, 
7
    mov     al, [
byte  Pattern + si]
    mov    ah, al
    and    al, bh
    mov    cx, bp
    mov    si, di
    push    es
    pop    ds
    dec    cx
    js    @@
2
      
out     dx, al
    movsb
    mov    al, ah
    
out     dx, al
    rep    movsb
@@
2 :
    and    al, bl
      
out     dx, al
    movsb
    pop    ds
    pop    si
    pop    di
    pop    cx
    inc    si
    add    di, DMWIDTH
    loop    @@
1
    pop    bp
    ret
ENDP
;
void  Bar(  int  x1,  int  y1,  int  x2,  int  y2 )
;
PROC    _Bar

    ARG    x1 : word, y1 : word, x2 : word, y2 : word
    USES    si, di

    mov    ax, [x1]
    mov    bx, [y1]
    mov    si, [x2]
    mov    di, [y2]
    mov    cx, [WidthX]
    mov    dx, [WidthY]
    call    TestPoint
    jc    @@
1
    add    ax, [MinX]
    add    bx, [MinY]
    add    si, [MinX]
    add    di, [MinY]
    push    ax
    call    SetWrMode0
    pop    ax
    call    Bar
    call    RestReg0
@@
1 :
    ret
ENDP
;
void  SetPalette( int  index,  int  Red,  int  Green,  int  Blus)
;
PROC    _SetPalette

    ARG    index : word, red : word, green : word, blus : word

    mov    al, [
byte  index]
    and    al, 0fh
    cmp    al, 
6
    jl    @@
2
    jg    @@
1
    mov    al, 14h
    jmp    
short  @@ 2
@@
1 :
    cmp    al, 
7
    je    @@
2
    add    al, 30h
@@
2 :
    mov    dx, 3c8h
    
out     dx, al
    inc    dx
    mov    al, [
byte  red]
    
out     dx, al
    mov    al, [
byte  green]
    
out     dx, al
    mov    al, [
byte  blus]
    
out     dx, al
    ret
ENDP
;
    END

       供其它汇编图形文件引用的插入文件:

; GRAPH.INC

    P386N
    include    tasm_c.inc

MAXCOLOR    equ    
15         ; 最大颜色值
MAXX        equ    
639         ; 最大 X 象素
MAXY        equ    
479         ; 最大 Y 象素
DSPMEMSEG    equ    0A000h        ; 屏显起始地址
DMWIDTH        equ    
80         ; 屏幕每线字节数
GRMODE        equ    12h        ; 屏显方式

EXTRN    Color:word
EXTRN    DrMode:word
EXTRN    MinX:word
EXTRN    MinY:word
EXTRN    MaxX:word
EXTRN    MaxY:word
EXTRN    WidthX:word
EXTRN    WidthY:word
;
EXTRN    _OpenGraph:proc
EXTRN    _CloseGraph:proc
EXTRN    _Line:proc
EXTRN    _PutPixel:proc
EXTRN    _GetPixel:proc
EXTRN    _SetColor:proc
EXTRN    _GetColor:proc
EXTRN    _SetDrMode:proc
EXTRN    _SetLnStyle:proc
EXTRN    _SetPattern:proc
EXTRN    _Rectangle:proc
EXTRN    _Bar:proc
EXTRN    _SetPalette:proc
EXTRN    _SetBorder:proc
EXTRN    _DefBorder:proc
EXTRN    GetDspMem:proc
EXTRN    GetDspMemOff:proc
EXTRN    SetWrMode:proc
EXTRN    SetWrMode0:proc
EXTRN    RestReg:proc
EXTRN    RestReg0:proc
EXTRN    TestPoint:proc
EXTRN    Bar:proc
EXTRN    GetPixel:proc
EXTRN    PutPixel:proc
EXTRN    _farmalloc:proc
EXTRN    _farfree:proc

        显示位图数据函数文件:

; grbmp.asm
    include    graph.inc

    CODESEG

    PUBLIC    _PutBmp
;
void  PutBmp( int  x,  int  y,  void  far  * bmp)
;
PROC    _PutBmp

    ARG    x : word, y :word, bmp : far ptr

    USES    si, di, ds

    mov    ah, 
2
    call    SetWrMode
    mov    ax, [x]
    mov    bx, [y]
    lds    si, [dword bmp]
    push    bp
    mov    bp, [si]
    add    bx, [si
+ 2 ]
    dec    bx
    push    ax
    call    GetDspMem
    pop    cx
    and    cx, 
7
    mov    ah, 80h
    shr    ah, cl
    mov    cx, [si
+ 2 ]
    add    si, 
4
@@
1 :
    push    bx
    push    ax
    xor    di, di
@@
2 :
    mov    al, ah
    
out     dx, al
    test    di, 
1
    jnz    @@
3
    lodsb
    shr    al, 
4
    jmp    
short  @@ 4
@@
3 :
    mov    al, [si
- 1 ]
    and    al, 0fh
@@
4 :
    xchg    al, [
byte  es:bx]
    ror    ah, 
1
    test    ah, 80h
    jz    @@
5
    inc    bx
@@
5 :
    inc    di
    cmp    di, bp
    jl    @@
2
    pop    ax
    pop    bx
    sub    bx, DMWIDTH
    loop    @@
1
    pop    bp
    call    RestReg
    ret
ENDP
;
    END

        PutBmp函数的测试程序:

/*  SHOWBMP.C  */

#include 
" graph.h "
#include 
< stdlib.h >
#include 
< stdio.h >
#include 
< string .h >
#include 
< alloc.h >

char   * buf  =  NULL;

void  PutBmp( int int void  far  * );

typedef    
struct
{
  unsigned 
char  blue;
  unsigned 
char  green;
  unsigned 
char  red;
  unsigned 
char  reserved;
}BMPRGB;

typedef 
struct
{
  
char  type[ 2 ];
  
long  filesize;
  
char  nul1[ 4 ];
  
long  offbins;
  
long  bisize;
  
long  width;
  
long  high;
  
int  planes;
  
int  bitcount;
  
long  packtype;
  
long  sizeimage;
  
long  xwidth;
  
long  ywidth;
  
long  clrused;
  
long  clrimportant;
  BMPRGB bmpcolor[
16 ];
}BMPTOP;

void  main( int  argc,  char   ** argv)
{
  
int  x, y,  * t;
  
char  s[ 10 ];
  unsigned size;
  BMPTOP p;
  BMPRGB 
* r;
  FILE 
* f;
  
if (argc  <   2 )
  {
    printf(
" Windows BMP 文件显示程序(VGA 16 色和非压缩格式) " );
    printf(
" 调用格式: SHOWBMP <BMP 文件名> " );
    
return ;
  }
  
if ((f  =  fopen(argv[ 1 ],  " rb " ))  ==  NULL)
  {
    printf(
" %s File not find! " , argv[ 1 ]);
    
return ;
  }
  fread(
& p,  1 sizeof (BMPTOP), f);
  
if (memcmp(p.type,  " BM " 2 ||  p.bitcount  !=   4   ||  p.packtype  !=   0 )
  {
    fclose(f);
    printf(
" %s 文件不是16色模式非压缩形式的BMP文件, 不能显示! " );
    
return ;
  }
  size 
=  p.filesize  -  p.offbins;
  
if ((buf  =  ( char   * )malloc(size  +   4 ))  ==  NULL)
  {
    printf(
" 文件太大, 内存不够使用! " );
    fclose(f);
    
return ;
  }
  size 
=  fread( & buf[ 4 ],  1 , size, f);
  fclose(f);
  
if (size  !=  p.filesize  -  p.offbins)
  {
    printf(
" %s 文件已坏 " );
    
return ;
  }
  t 
=  ( int   * )buf;
  
* ++   =  p.width;
  
* =  p.high;
  OpenGraph();
  r 
=  (BMPRGB  * )p.bmpcolor;
  
for (x  =   0 ; x  <   16 ; x  ++  )
    SetPalette( x, r[x].red 
>>   2 , r[x].green  >>   2 , r[x].blue  >>   2 );
  x 
=  ( 640   -  p.width)  >>   1 ;
  y 
=  ( 480   -  p.high)  >>   1 ;
  SetColor(
8 );
  Bar(x 
-   10 , y  -   10 , x  +  p.width  +   10 , y  +  p.high  +   10 );
  PutBmp(x, y, buf);
  gets(s);
  CloseGraph();
}

未完待续。

===================================================================================

        更新:有个现成的UCDOS字符串显示测试程序,其中还包括了GetImage和PutImage函数的测试,这些函数代码在《Turbo C使用的汇编函数 -- VGA 12H模式图形函数(二)》中,因那篇文章代码太多,太长,所以补充更新在此,供参考:

#include  " graph.h "
#include 
< alloc.h >
#include 
< stdio.h >

void  main()
{
  
int  i, j, k;
  unsigned s1, s2;
  
char  ss[ 9 ];
  
void  far  * s;
  OpenGraph();
  
if ( ! InitUCDOS( 2 ))
    
return ;
  
for (i  =   0 , k  =   1 ; i  <   128 ; i  +=   16 , k  ++ )
    {
      SetPos(
0 , i);
      Putch(k 
+   33 80 , k);
    }
  Putss(
10 128 " 公安县统计局 " 640 15 );
  s1 
=  ImageSize( 0 0 639 127 );
  s 
=  farmalloc(s1);
  
if (s)
  {
    s2 
=  GetImage( 0 0 639 127 , s);
    PutImage(
0 150 , s,  0 );
    gets(ss);
  }
  RestUCDOS(
0 );
  CloseGraph();
  
if ( ! s)
    printf(
" Error! " );
  
else
    printf(
" s1 = %u, s2 = %u " , s1, s2);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值