NASM:如何使用英特尔 64 位程序集创建/处理基本的 bmp 文件?

asd*_*fgh 0 linux x86 assembly x86-64 nasm

如何仅使用英特尔 64 位汇编和 nasm 汇编器创建/处理用一种颜色填充的简单 bmp 文件?

asd*_*fgh 6

包括此类操作的步骤是:

  1. 创建具有固定值的 bmp 文件头(具体字段说明如下)
  2. 创建包含足够空间的缓冲区 - 每像素三个字节(一种颜色 = 红色 + 绿色 + 蓝色)
  3. 打开/创建文件
  4. 填充缓冲区
  5. 将头文件写入文件
  6. 将缓冲区写入文件
  7. 关闭文件
  8. 退出程序

广告。2:这有点棘手 - 如果每行的像素数不能被 4 整除,程序必须用 0xFF 填充缺少的字节。在这里,我特意创建了一张 201x201 的图片。在这个例子中,我们可以看到每行将有 3*201=603 个字节,这意味着每行需要额外的字节。因此,图片缓冲区所需的大小为 604*201=121404。

回答问题的源代码:

section     .text
global      _start                              ;must be declared for linker (ld)

_start:                                         ;tell linker entry point

;#######################################################################
;### This program creates empty bmp file - 64 bit version ##############
;#######################################################################
;### main ##############################################################
;#######################################################################

    ; open file
    mov     rax,85                              ;system call number - open/create file
    mov     rdi,msg                             ;file name
                                                ;flags
    mov     rsi,111111111b                      ;mode
    syscall                                     ;call kernel

    ; save file descriptor
    mov     r8, rax

    ; write headline to file
    mov     rax, 1                              ;system call number - write
    mov     rdi, r8                             ;load file desc
    mov     rsi, bmpheadline                    ;load adress of buffer to write
    mov     rdx, 54                             ;load number of bytes
    syscall                                     ;call kernel

        mov         rbx, 201                    ;LOOPY counter
        mov         rdx, empty_space            ;load address of buffer (space allocated for picture pixels)
LOOPY:
        mov         rcx, 201                    ;LOOPX counter

LOOPX:
        mov         byte [rdx+0], 0x00          ;BLUE
        mov         byte [rdx+1], 0xFF          ;GREEN
        mov         byte [rdx+2], 0xFF          ;RED

        dec         rcx                         ;decrease counter_x
        add         rdx, 3                      ;move address pointer by 3 bytes (1 pixel = 3 bytes, which we just have written)
        cmp         rcx, 0                      ;check if counter is 0
        jne         LOOPX                       ;if not jump to LOOPX

        dec         rbx                         ;decrease counter_y
        mov         byte [rdx], 0xFF            ;additional byte per row
        inc         rdx                         ;increase address
        cmp         rbx, 0                      ;check if counter is 0
        jne         LOOPY                       ;if not jump to LOOPY



    ; write content to file
    mov     rax, 1                              ;system call number - write
    mov     rdi, r8                             ;load file desc
    mov     rsi, empty_space                    ;load adress of buffer to write
    mov     rdx, 121404                         ;load number of bytes
    syscall                                     ;call kernel

    ; close file
    mov     rax, 3                              ;system call number - close
    mov     rdi, r8                             ;load file desc
    syscall                                     ;call kernel

    ; exit program
    mov     rax,60                              ;system call number - exit
    syscall                                     ;call kernel

section     .data

    msg         db  'filename.bmp',0x00         ;name of out file, 0x00 = end of string
    bmpheadline db  0x42,0x4D,0x72,0xDA,0x01,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0xC9,0x00,0x00,0x00,0xC9,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x3C,0xDA,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

section .bss                                    ;this section is responsible for preallocated block of memory of fixed size

    empty_space: resb 121404                    ;preallocation of 121404 bytes
Run Code Online (Sandbox Code Playgroud)

这里是bmp标题的解释(更多在这个链接下:http : //www.dragonwins.com/domains/getteched/bmp/bmpfileformat.htm

;### File Header - 14 bytes
;#######################################################################
;### bfType,        2 bytes,    The characters "BM"
;### 0x42,0x4D = "B","M"
;### 
;### bfSize,        4 bytes,    The size of the file in bytes
;### 0x72,0xDA,0x01,0x00 => 0x00,0x01,0xDA,0x72 = 0x1DA72 = 121458 bytes
;### 121458 = 54 + 201 * (201 + 1) * 3
;### 
;### Comment:
;### We want to create file 201x201, that means 201 rows and 201 columns
;### meaning each row will take 201*3 = 603 bytes
;### 
;### According to BMP file specification each such row must be adjusted
;### so its size is dividable by 4, this gives us plus 1 byte for each 
;### row.
;###
;###
;### bfReserved1,   2 bytes,    Unused - must be zero
;### 0x00,0x00
;### 
;### bfReserved2,   2 bytes,    Unused - must be zero
;### 0x00,0x00
;### 
;### bfOffBits,     4 bytes,    Offset to start of Pixel Data
;### 0x36,0x00,0x00,0x00 = 54 bytes
;### 

;### Image Header - 40 bytes
;#######################################################################
;### biSize             4   Header Size - Must be at least 40
;### 0x28,0x00,0x00,0x00 = 40
;### 
;### biWidth            4   Image width in pixels
;### 0xC9,0x00,0x00,0x00 = 201
;### 
;### biHeight           4   Image height in pixels
;### 0xC9,0x00,0x00,0x00 = 201
;### 
;### biPlanes           2   Must be 1
;### 0x01,0x00
;### 
;### biBitCount         2   Bits per pixel - 1, 4, 8, 16, 24, or 32
;### 0x18,0x00 = 24
;### 
;### biCompression      4   Compression type (0 = uncompressed)
;### 0x00,0x00,0x00,0x00
;### 
;### biSizeImage        4   Image Size - may be zero for uncompressed images
;### 0x3C,0xDA,0x01,0x00 => 0x00,0x01,0xDA,0x3C = 121404 bytes
;### 
;### biXPelsPerMeter    4   Preferred resolution in pixels per meter
;### 0x00,0x00,0x00,0x00
;### 
;### biYPelsPerMeter    4   Preferred resolution in pixels per meter
;### 0x00,0x00,0x00,0x00
;### 
;### biClrUsed          4   Number Color Map entries that are actually used
;### 0x00,0x00,0x00,0x00
;### 
;### biClrImportant     4   Number of significant colors
;### 0x00,0x00,0x00,0x00
;### 
Run Code Online (Sandbox Code Playgroud)