使用16位汇编显示bmp

来源:互联网 发布:贝乐虎儿歌软件 编辑:程序博客网 时间:2024/06/02 16:14

(写于November 18th, 2013)

   因为比赛要求使用16位汇编写一个游戏,开始设想如果可以显示图片的话会更加好。

   寻找了各种办法终于实现了显示256色的位图,但是防止数据段超过64k最终还是没有使用。还是写下来留作纪念吧。

   

   首先我们需要了解清楚bmp文件的结构,下面是关于bmp(位图)结构体的介绍:

1. BMP文件组成

BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

2. BMP文件头(14字节)

BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。

其结构定义如下:

typedef struct tagBITMAPFILEHEADER {     WORD bfType; // 位图文件的类型,必须为BM(1-2字节)     DWORD bfSize; // 位图文件的大小,以字节为单位(3-6字节)     WORD bfReserved1; // 位图文件保留字,必须为0(7-8字节)     WORD bfReserved2; // 位图文件保留字,必须为0(9-10字节)     DWORD bfOffBits; // 位图数据的起始位置,以相对于位图(11-14字节)     // 文件头的偏移量表示,以字节为单位 } BITMAPFILEHEADER;

3. 位图信息头(40字节)

BMP位图信息头数据用于说明位图的尺寸等信息。

typedef struct tagBITMAPINFOHEADER{     DWORD biSize; // 本结构所占用字节数(15-18字节)     LONG biWidth; // 位图的宽度,以像素为单位(19-22字节)     LONG biHeight; // 位图的高度,以像素为单位(23-26字节)     WORD biPlanes; // 目标设备的级别,必须为1(27-28字节)     WORD biBitCount;// 每个像素所需的位数,必须是1(双色),(29-30字节)     // 4(16色),8(256色)16(高彩色)或24(真彩色)之一     DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),(31-34字节)     // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一     DWORD biSizeImage; // 位图的大小,以字节为单位(35-38字节)     LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(39-42字节)     LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(43-46字节)     DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数(47-50字节)     DWORD biClrImportant;// 位图显示过程中重要的颜色数(51-54字节) } BITMAPINFOHEADER;

4. 颜色表

颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

typedef struct tagRGBQUAD {     BYTE rgbBlue;// 蓝色的亮度(值范围为0-255)     BYTE rgbGreen; // 绿色的亮度(值范围为0-255)     BYTE rgbRed; // 红色的亮度(值范围为0-255)     BYTE rgbReserved;// 保留,必须为0 } RGBQUAD;

颜色表中RGBQUAD结构数据的个数有biBitCount来确定:

当biBitCount=1,4,8时,分别有2,16,256个表项;

当biBitCount=24时,没有颜色表项。

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:

typedef struct tagBITMAPINFO {     BITMAPINFOHEADER bmiHeader; // 位图信息头     RGBQUAD bmiColors[1]; // 颜色表 } BITMAPINFO;

5. 位图数据

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:

当biBitCount=1时,8个像素占1个字节;

当biBitCount=4时,2个像素占1个字节;

当biBitCount=8时,1个像素占1个字节;

当biBitCount=24时,1个像素占3个字节;

Windows规定一个扫描行所占的字节数必须是

4的倍数(即以long为单位),不足的以0填充,

biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight;

下面汇编代码是以以显示320*200256色位图为例:

;------------------------------------------------------------------------------------------; 数据段定义data segment    pathname db '1.bmp', 00    ; 图片路径    x0 dw 0    y0 dw 0              handle dw ?                ; 文件指针    bmpdata1 db 256*4 dup(?)   ; 存放位图文件调色板    bmpdata2 db 64000 dup(0)   ; 存放位图信息    bmpwidth dw ?              ; 位图宽度    bmplength dw ?          ; 位图长度    pelsnum dw ?               ; temp num    num dw ?    flag dw ?                  ; scren set    screnwidth dw 320    screnlength dw 200data ends                        ;stackstack1 segment stack       dw 100h dup(?)stack1 ends                        ; codeprognam segment    assume cs:prognam, ds:data, ss:stack1main proc far    ; main part of the program    mov ax, data    mov ds, ax                                call openf    call getinfo    call readf    call dispy1    call dispy2main endp                        ;---------------------------------------------------; 打开文件并存令handle指向文件openf proc near    lea dx, pathname            ; ah = 3dh,al = 0 打开文件并读取,成功存入AX    mov ah, 3dh    mov al, 0    int 21h    mov handle, ax    retopenf endp                        ;--------------------------------------------------; 获取位图信息函数getinfo proc near        ; 移动文件指针,bx = 文件代号, cx:dx = 位移量, al = 0即从文件头绝对位移        mov ah, 42h        mov al, 0        mov bx, handle        mov cx, 0        mov dx, 12h     ; 跳过18个字节直接指向位图的宽度信息        int 21h        ; 读取文件,ds:dx = 数据缓冲区地址, bx = 文件代号, cx = 读取的字节数, ax = 0表示已到文件尾        mov ah, 3fh        lea dx, bmpwidth        ; 存放位图宽度        mov cx, 2        int 21h        mov ah, 42h        mov al, 0        mov bx, handle        mov cx, 0        mov dx, 16h     ; 跳过22个字节直接指向位图的长度信息        int 21h        mov ah, 3fh        lea dx, bmplength       ; 存放位图长度        mov cx, 2        int 21h        mov ax, bmpwidth        mul bmplength        mov pelsnum, ax         ; 计算出位图大小放入pelsnum中        retgetinfo endp                        ;---------------------------------------------------; 读取位图颜色信息readf proc near        ; 跳过前54个字节进入颜色信息        mov ah, 42h        mov al, 0        mov bx, handle        mov cx, 0        mov dx, 36h           int 21h        mov ah, 3fh        lea dx, bmpdata1        ; 将颜色信息放入bmpdata1        mov cx, 256*4           ; 蓝+绿+红+色彩保留(0)一共占256*4个字节        int 21h        retreadf endp                        ;-------------------------------------------------------;display 函数dispy1 proc near       ; 设置256色,320*200像素       mov ax, 0013h       int 10h       ; 设置调色板输出色彩索引号及rgb数据共写256次       mov cx, 256       lea si, bmpdata1         ; 颜色信息p:       mov dx, 3c8h             ; 设定i/o端口       mov ax, cx       dec ax       neg ax                   ; 求补       add ax, 255              ; ax = ffffh(al = ffh, ah = ffh)       out dx, al               ; 将al中的数据传入dx指向的i/o端口中       inc dx       ; bmp调色板存放格式:bgr~bgr~...(~为空00h)       ; rgb/4后写入,显卡要求,rgb范围(0~63),位图中(0~255)       mov al, [si+2]                  shr al, 1                     shr al, 1       out dx, al       mov al, [si+1]       shr al, 1       shr al, 1       out dx, al       mov al, [si]       shr al, 1       shr al, 1       out dx, al       add si, 4       loop p       retdispy1 endp                        ;--------------------------------------------------dispy2 proc near        mov bx, 0a000h          ; 40k        mov es, bxdp30:        mov di, 0        cld                     ; df清零        mov cx, y0              ; cx = 0dp00:        mov ax, bmpwidth        ; ax = 位图宽度        mov dx, ax        and dx, 11b        jz dp000        mov ax, 4        sub ax, dx        add ax, bmpwidthdp000:        inc cx        mul cx        dec cx        mov bx, 0        sub bx, ax        mov ax, bx        mov bx, 0        sbb bx, dx        mov dx, bx        push cx        mov cx, dx        mov dx, ax        mov bx, handle        mov ax, 4202h        int 21h        mov dx, offset bmpdata2        mov cx, bmpwidth        mov ah, 3fh        int 21h        pop cx        cmp ax, bmpwidth        jb dp3        mov si, offset bmpdata2        add si, x0dp0:        push di        mov dx, 0 dp1:        lodsb        stosb        inc dx        cmp dx, 320        jae dp2        push dx        add dx, x0        cmp dx, bmpwidth        pop dx        jb dp1dp2:        pop di        add di, 320        inc cx        push cx        sub cx, y0        cmp cx, 200        pop cx        jae dp3        push cx        cmp cx, bmplength        pop cx        jb dp00 dp3:        mov ah,0        int 16h        cmp ax, 4800h        je up        cmp ax, 4b00h        je left        cmp ax, 4d00h        je right        cmp ax, 5000h        je down        cmp ax, 011bh        je exit        jmp dp3up:        mov ax, y0        sub ax, 1        jl dp3        mov y0, ax        jmp dp30down:        mov ax, y0        add ax, 1        push ax        add ax, 200        cmp ax, bmplength        pop ax        jae dp3        mov y0,ax        jmp dp30left:        mov ax, x0        sub ax, 1        jl dp3        mov x0, ax        jmp dp30right:        mov ax, x0        add ax, 1        push ax        add ax, 320        cmp ax, bmpwidth        pop ax        jae dp3        mov x0, ax        jmp dp30                        exit:        mov ax, 3        int 10h        mov ax, 4c00h        int 21hxp1:        mov ax, bmplength        mul screnwidth        mov num, ax        lea si, bmpdata2        mov cx, bmpwidth        push cx        mov ax, bmplength        mov flag, ax        dec flag        sub num, 320        mov di, num                                add di, 320        add di, bmpwidthl2:        sub di, 320        sub di, bmpwidth        cmp flag, 0        jz l3        dec flag        pop cx        push cxdis:        mov al, [si]        mov ah, 0        stosb        add si, 1        cmp cx, 1        jz l2        loop disl3:        mov ah, 0        int 16h        mov ax, 3        int 10h        mov ax, 4c00h        int 21hdispy2 endp                        prognam ends    end main

在dosbox中的显示效果: 
 
(由于将图片处理为256色,相对原图可能有些失真)


原创粉丝点击