Bootstrap

使用16位汇编显示bmp位图

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

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

1. BMP文件组成

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

2. BMP文件头(14字节)

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

其结构定义如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. typedef struct tagBITMAPFILEHEADER  
  2.  {  
  3.      WORD bfType; // 位图文件的类型,必须为BM(1-2字节)  
  4.      DWORD bfSize; // 位图文件的大小,以字节为单位(3-6字节)  
  5.      WORD bfReserved1; // 位图文件保留字,必须为0(7-8字节)  
  6.      WORD bfReserved2; // 位图文件保留字,必须为0(9-10字节)  
  7.      DWORD bfOffBits; // 位图数据的起始位置,以相对于位图(11-14字节)  
  8.      // 文件头的偏移量表示,以字节为单位  
  9.  } BITMAPFILEHEADER;  

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

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

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

4. 颜色表

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. typedef struct tagRGBQUAD {  
  2.      BYTE rgbBlue;// 蓝色的亮度(值范围为0-255)  
  3.      BYTE rgbGreen; // 绿色的亮度(值范围为0-255)  
  4.      BYTE rgbRed; // 红色的亮度(值范围为0-255)  
  5.      BYTE rgbReserved;// 保留,必须为0  
  6.  } RGBQUAD;  

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

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

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. typedef struct tagBITMAPINFO {  
  2.      BITMAPINFOHEADER bmiHeader; // 位图信息头  
  3.      RGBQUAD bmiColors[1]; // 颜色表  
  4.  } BITMAPINFO;  

5. 位图数据

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

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

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

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

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

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight;  
下面汇编代码是以以显示 320*200 256 色位图为例:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. ;------------------------------------------------------------------------------------------  
  2. ; 数据段定义  
  3. data segment  
  4.     pathname db '1.bmp', 00    ; 图片路径  
  5.     x0 dw 0  
  6.     y0 dw 0            
  7.     handle dw ?                ; 文件指针  
  8.     bmpdata1 db 256*4 dup(?)   ; 存放位图文件调色板  
  9.     bmpdata2 db 64000 dup(0)   ; 存放位图信息  
  10.     bmpwidth dw ?              ; 位图宽度  
  11.     bmplength dw ?          ; 位图长度  
  12.     pelsnum dw ?               ; temp num  
  13.     num dw ?  
  14.     flag dw ?                  ; scren set  
  15.     screnwidth dw 320  
  16.     screnlength dw 200  
  17. data ends  
  18.                           
  19. ;stack  
  20. stack1 segment stack  
  21.        dw 100h dup(?)  
  22. stack1 ends  
  23.                           
  24. ; code  
  25. prognam segment  
  26.     assume cs:prognam, ds:data, ss:stack1  
  27. main proc far  
  28.     ; main part of the program  
  29.     mov ax, data  
  30.     mov ds, ax  
  31.                               
  32.     call openf  
  33.     call getinfo  
  34.     call readf  
  35.     call dispy1  
  36.     call dispy2  
  37. main endp  
  38.                           
  39. ;---------------------------------------------------  
  40. ; 打开文件并存令handle指向文件  
  41. openf proc near  
  42.     lea dx, pathname          
  43.     ; ah = 3dh,al = 0 打开文件并读取,成功存入AX  
  44.     mov ah, 3dh  
  45.     mov al, 0  
  46.     int 21h  
  47.     mov handle, ax  
  48.     ret  
  49. openf endp  
  50.                           
  51. ;--------------------------------------------------  
  52. ; 获取位图信息函数  
  53. getinfo proc near  
  54.         ; 移动文件指针,bx = 文件代号, cx:dx = 位移量, al = 0即从文件头绝对位移  
  55.         mov ah, 42h  
  56.         mov al, 0  
  57.         mov bx, handle  
  58.         mov cx, 0  
  59.         mov dx, 12h     ; 跳过18个字节直接指向位图的宽度信息  
  60.         int 21h  
  61.         ; 读取文件,ds:dx = 数据缓冲区地址, bx = 文件代号, cx = 读取的字节数, ax = 0表示已到文件尾  
  62.         mov ah, 3fh  
  63.         lea dx, bmpwidth        ; 存放位图宽度  
  64.         mov cx, 2  
  65.         int 21h  
  66.         mov ah, 42h  
  67.         mov al, 0  
  68.         mov bx, handle  
  69.         mov cx, 0  
  70.         mov dx, 16h     ; 跳过22个字节直接指向位图的长度信息  
  71.         int 21h  
  72.         mov ah, 3fh  
  73.         lea dx, bmplength       ; 存放位图长度  
  74.         mov cx, 2  
  75.         int 21h  
  76.         mov ax, bmpwidth  
  77.         mul bmplength  
  78.         mov pelsnum, ax         ; 计算出位图大小放入pelsnum中  
  79.         ret  
  80. getinfo endp  
  81.                           
  82. ;---------------------------------------------------  
  83. ; 读取位图颜色信息  
  84. readf proc near  
  85.         ; 跳过前54个字节进入颜色信息  
  86.         mov ah, 42h  
  87.         mov al, 0  
  88.         mov bx, handle  
  89.         mov cx, 0  
  90.         mov dx, 36h     
  91.         int 21h  
  92.         mov ah, 3fh  
  93.         lea dx, bmpdata1        ; 将颜色信息放入bmpdata1  
  94.         mov cx, 256*4           ; 蓝+绿+红+色彩保留(0)一共占256*4个字节  
  95.         int 21h  
  96.         ret  
  97. readf endp  
  98.                           
  99. ;-------------------------------------------------------  
  100. ;display 函数  
  101. dispy1 proc near  
  102.        ; 设置256色,320*200像素  
  103.        mov ax, 0013h  
  104.        int 10h  
  105.        ; 设置调色板输出色彩索引号及rgb数据共写256次  
  106.        mov cx, 256  
  107.        lea si, bmpdata1         ; 颜色信息  
  108. p:  
  109.        mov dx, 3c8h             ; 设定i/o端口  
  110.        mov ax, cx  
  111.        dec ax  
  112.        neg ax                   ; 求补  
  113.        add ax, 255              ; ax = ffffh(al = ffh, ah = ffh)  
  114.        out dx, al               ; 将al中的数据传入dx指向的i/o端口中  
  115.        inc dx  
  116.        ; bmp调色板存放格式:bgr~bgr~...(~为空00h)  
  117.        ; rgb/4后写入,显卡要求,rgb范围(0~63),位图中(0~255)  
  118.        mov al, [si+2]             
  119.        shr al, 1                
  120.        shr al, 1  
  121.        out dx, al  
  122.        mov al, [si+1]  
  123.        shr al, 1  
  124.        shr al, 1  
  125.        out dx, al  
  126.        mov al, [si]  
  127.        shr al, 1  
  128.        shr al, 1  
  129.        out dx, al  
  130.        add si, 4  
  131.        loop p  
  132.        ret  
  133. dispy1 endp  
  134.                           
  135. ;--------------------------------------------------  
  136. dispy2 proc near  
  137.         mov bx, 0a000h          ; 40k  
  138.         mov es, bx  
  139. dp30:  
  140.         mov di, 0  
  141.         cld                     ; df清零  
  142.         mov cx, y0              ; cx = 0  
  143. dp00:  
  144.         mov ax, bmpwidth        ; ax = 位图宽度  
  145.         mov dx, ax  
  146.         and dx, 11b  
  147.         jz dp000  
  148.         mov ax, 4  
  149.         sub ax, dx  
  150.         add ax, bmpwidth  
  151. dp000:  
  152.         inc cx  
  153.         mul cx  
  154.         dec cx  
  155.         mov bx, 0  
  156.         sub bx, ax  
  157.         mov ax, bx  
  158.         mov bx, 0  
  159.         sbb bx, dx  
  160.         mov dx, bx  
  161.         push cx  
  162.         mov cx, dx  
  163.         mov dx, ax  
  164.         mov bx, handle  
  165.         mov ax, 4202h  
  166.         int 21h  
  167.         mov dx, offset bmpdata2  
  168.         mov cx, bmpwidth  
  169.         mov ah, 3fh  
  170.         int 21h  
  171.         pop cx  
  172.         cmp ax, bmpwidth  
  173.         jb dp3  
  174.         mov si, offset bmpdata2  
  175.         add si, x0  
  176. dp0:  
  177.         push di  
  178.         mov dx, 0   
  179. dp1:  
  180.         lodsb  
  181.         stosb  
  182.         inc dx  
  183.         cmp dx, 320  
  184.         jae dp2  
  185.         push dx  
  186.         add dx, x0  
  187.         cmp dx, bmpwidth  
  188.         pop dx  
  189.         jb dp1  
  190. dp2:  
  191.         pop di  
  192.         add di, 320  
  193.         inc cx  
  194.         push cx  
  195.         sub cx, y0  
  196.         cmp cx, 200  
  197.         pop cx  
  198.         jae dp3  
  199.         push cx  
  200.         cmp cx, bmplength  
  201.         pop cx  
  202.         jb dp00   
  203. dp3:  
  204.         mov ah,0  
  205.         int 16h  
  206.         cmp ax, 4800h  
  207.         je up  
  208.         cmp ax, 4b00h  
  209.         je left  
  210.         cmp ax, 4d00h  
  211.         je right  
  212.         cmp ax, 5000h  
  213.         je down  
  214.         cmp ax, 011bh  
  215.         je exit  
  216.         jmp dp3  
  217. up:  
  218.         mov ax, y0  
  219.         sub ax, 1  
  220.         jl dp3  
  221.         mov y0, ax  
  222.         jmp dp30  
  223. down:  
  224.         mov ax, y0  
  225.         add ax, 1  
  226.         push ax  
  227.         add ax, 200  
  228.         cmp ax, bmplength  
  229.         pop ax  
  230.         jae dp3  
  231.         mov y0,ax  
  232.         jmp dp30  
  233. left:  
  234.         mov ax, x0  
  235.         sub ax, 1  
  236.         jl dp3  
  237.         mov x0, ax  
  238.         jmp dp30  
  239. right:  
  240.         mov ax, x0  
  241.         add ax, 1  
  242.         push ax  
  243.         add ax, 320  
  244.         cmp ax, bmpwidth  
  245.         pop ax  
  246.         jae dp3  
  247.         mov x0, ax  
  248.         jmp dp30  
  249.                           
  250. exit:  
  251.         mov ax, 3  
  252.         int 10h  
  253.         mov ax, 4c00h  
  254.         int 21h  
  255. xp1:  
  256.         mov ax, bmplength  
  257.         mul screnwidth  
  258.         mov num, ax  
  259.         lea si, bmpdata2  
  260.         mov cx, bmpwidth  
  261.         push cx  
  262.         mov ax, bmplength  
  263.         mov flag, ax  
  264.         dec flag  
  265.         sub num, 320  
  266.         mov di, num  
  267.                           
  268.         add di, 320  
  269.         add di, bmpwidth  
  270. l2:  
  271.         sub di, 320  
  272.         sub di, bmpwidth  
  273.         cmp flag, 0  
  274.         jz l3  
  275.         dec flag  
  276.         pop cx  
  277.         push cx  
  278. dis:  
  279.         mov al, [si]  
  280.         mov ah, 0  
  281.         stosb  
  282.         add si, 1  
  283.         cmp cx, 1  
  284.         jz l2  
  285.         loop dis  
  286. l3:  
  287.         mov ah, 0  
  288.         int 16h  
  289.         mov ax, 3  
  290.         int 10h  
  291.         mov ax, 4c00h  
  292.         int 21h  
  293. dispy2 endp  
  294.                           
  295. prognam ends      
  296. end main  



;