0

我正在汇编程序中编程,我想打开一个 .bmp 图像并在屏幕上显示它,但我不知道该怎么做。我不想使用任何外部库来做到这一点。有谁知道我可以研究这个的文章或网站?谢谢。

观察。我正在使用 Linux 和 NASM。

4

2 回答 2

1

如果您不想使用任何外部库,则需要自己实现整个 BMP 文件格式,因此BMP 规范将是一个很好的起点。

至于显示图像,您打算如何控制显示?您可能不想直接与硬件对话;这基本上意味着编写自己的视频驱动程序。您可以连接到 X11 显示器,但这涉及外部库(Xlib 或 XCB)。

无论如何,这在组装中将是相当乏味的。通常,汇编保留用于在高级语言中无法完成(足够快或根本无法完成)的专门任务。显示图像不是这些任务之一。

于 2012-04-27T05:49:04.977 回答
0

这个示例程序创建一个位图并在其中画一条线。

; Program to draw lines to 1000x1000 Bitmap File
; Compile with:
;     nasm -f elf64 -o drawLines64.o drawLines64.asm
; Link with:
;     ld -m elf_x86_64 -o drawLines64 drawLines64.o
; Run with:
;     ./drawLines64
;==============================================================================
; Author : Rommel Samanez
; https://github.com/rsamanez/assemblerx64
;==============================================================================

global _start


section .data
  fileName:  db "lines.bmp",0
  fileFlags: dq 0102o         ; create file + read and write mode
  fileMode:  dq 00600o        ; user has read write permission
  fileDescriptor: dq 0
  bitmapImage: times 3000000 db 0
section .rodata    ; read only data section
    bmpWidth   equ  1000
    bmpHeight   equ  1000
    bmpSize equ 3 * bmpWidth * bmpHeight
    headerLen equ 54
    header: db "BM"         ; BM  Windows 3.1x, 95, NT, ... etc.
    bfSize: dd bmpSize + headerLen   ; The size of the BMP file in bytes
            dd 0                 ; reserved
    bfOffBits: dd headerLen   ; The offset, i.e. starting address, of the byte where the bitmap image data (pixel array) can be found
    biSize:   dd 40    ; header size, min = 40
    biWidth:  dd bmpWidth
    biHeight: dd bmpHeight
    biPlanes:       dw 1     ; must be 1
    biBitCount:     dw 24    ; bits per pixel: 1, 4, 8, 16, 24, or 32
    biCompression:  dd 0     ; uncompressed = 0
    biSizeImage:    dd bmpSize  ; Image Size - may be zero for uncompressed images
    hresolution:    dd 0
    vresolution:    dd 0
    palettecolors:  dd 0
    importantcolors: dd 0

section .text

; drawPixel(x,y,color{RGB}) ( R8,R9,R10) 
drawPixel:
    push rax
    push rbx
    ;---------------------------------
    mov rax,3000
    mul r9
    push rax
    mov rax,3
    mul r8
    pop rbx
    add rax,rbx         ; offset:  rax = 3*x+3000*y
    push r10
    pop rbx
    mov word[bitmapImage+rax],bx
    shr rbx,16
    mov byte[bitmapImage+rax+2],bl
    ;----------------------------------
    pop rbx
    pop rax
    ret
; drawLine(x1,y1,x2,y2,color) color = R10  x1=r8 y1=r9 x2=r11 y2=r12    
drawLine:
    push rax
    push rbx
    push rcx                  ;  line   y = M*x/1000   M=w*1000/q  w=y2-y1  q=x2-x1 
    push rdx
    ;-----------------------------------
    mov rax,r12             ; rax <- y2
    sub rax,r9              ; rax <- y2 - y1
    mov rbx,1000
    mul rbx                 ; rax <- rax*1000
    mov rbx,r11             ; rbx <- x2
    sub rbx,r8              ; rbx <- x2 - x1
    xor rdx,rdx             ; rdx = 0
    div rbx                 ; RAX / RBX  RAX= value  M
    push rax
    pop rcx                 ; rcx <- M
    mov rbx,r8              ; rbx <- x1
    ;-----------------------------------------
    push r8
    push r9
nextPixel:
    mov rax,rbx             ; rbx = x
    mul rcx                 ; rax = M*x
    push rcx
    xor rdx,rdx
    mov rcx,1000
    div rcx                 ; rax = M*x/1000
    pop rcx
    mov r8,rbx              ; r8 <- x
    mov r9,rax              ; r9 <- y
    call drawPixel
    inc rbx
    cmp rbx,r11
    jnz nextPixel
    pop r9
    pop r8
    ;-----------------------------------
    pop rdx
    pop rcx
    pop rbx
    pop rax
    ret


drawLines:
    mov r8,0
    mov r9,0
    mov r10,0xff0000        ; color RED
    mov r11,900
    mov r12,900
    call drawLine
    ret  

_start:
    mov rax,2                 ;   sys_open
    mov rdi,fileName          ;   const char *filename
    mov rsi,[fileFlags]       ;   int flags
    mov rdx,[fileMode]        ;   int mode
    syscall
    mov [fileDescriptor],rax

    ; write the header to file
    mov rax,1                 ; sys_write
    mov rdi,[fileDescriptor]
    mov rsi,header
    mov rdx,54
    syscall

    call drawLines

    ; write the Image to file
    mov rax,1                 ; sys_write
    mov rdi,[fileDescriptor]
    mov rsi,bitmapImage
    mov rdx,3000000
    syscall

    ; close file Descriptor
    mov rax,3                 ; sys_close
    mov rdi,[fileDescriptor]
    syscall

    ; EXIT to OS  sys_exit
    mov rax,60
    mov rdi,0
    syscall
于 2019-04-07T22:37:39.640 回答