在 TASM 8086 中加载多张图片

问题描述 投票:0回答:1
IDEAL
MODEL small
STACK 100h
p386
DATASEG
filename1 db 'picture1.bmp',0
filename2 db 'instructions.bmp',0
filehandle1 dw ?
filehandle2 dw ?
Header1 db 54 dup (0)
Header2 db 54 dup (0)
Palette1 db 256*4 dup (0)
Palette2 db 256*4 dup (0)
ScrLine1 db 320 dup (0)
ScrLine2 db 320 dup (0)
ErrorMsg1 db 'Error', 13, 10 ,'$'
ErrorMsg2 db 'Error', 13, 10 ,'$'




CODESEG
; The following procedures are picture related
;-------------------------------------------------------------------
;Prints the bmp file provided
;IN: ax - img offset, imgHeight (dw), imgWidth (dw), printAdd (dw)
;OUT: printed bmp file
proc OpenFile1
; Open file
mov ah, 3Dh
xor al, al
mov dx, offset filename1
int 21h
jc openerror1
mov [filehandle1], ax
ret
openerror1 :
mov dx, offset ErrorMsg1
mov ah, 9h
int 21h
ret
endp OpenFile1
proc ReadHeader1
; Read BMP file header, 54 bytes
mov ah,3fh
mov bx, [filehandle1]
mov cx,54
mov dx,offset Header1
int 21h
ret
endp ReadHeader1
proc ReadPalette1
; Read BMP file color palette, 256 colors * 4 bytes (400h)
mov ah,3fh
mov cx,400h
mov dx,offset Palette1
int 21h
ret
endp ReadPalette1
proc CopyPal1
; Copy the colors palette to the video memory
; The number of the first color should be sent to port 3C8h
; The palette is sent to port 3C9h
mov si,offset Palette1
mov cx,256
mov dx,3C8h
mov al,0
; Copy starting color to port 3C8h
out dx,al
; Copy palette itself to port 3C9h
inc dx
PalLoop1:
; Note: Colors in a BMP file are saved as BGR values rather than RGB .
mov al,[si+2] ; Get red value .
shr al,2 ; Max. is 255, but video palette maximal
; value is 63. Therefore dividing by 4.
out dx,al ; Send it .
mov al,[si+1] ; Get green value .
shr al,2
out dx,al ; Send it .
mov al,[si] ; Get blue value .
shr al,2
out dx,al ; Send it .
add si,4 ; Point to next color .
; (There is a null chr. after every color.)
loop PalLoop1
ret
endp CopyPal1
proc CopyBitmap1
; BMP graphics are saved upside-down .
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
mov ax, 0A000h
mov es, ax
mov cx,200
PrintBMPLoop1 :
push cx
; di = cx*320, point to the correct screen line
mov di,cx
shl cx,6
shl di,8
add di,cx
; Read one line
mov ah,3fh
mov cx,320
mov dx,offset ScrLine1
int 21h
; Copy one line into video memory
cld ; Clear direction flag, for movsb
mov cx,320
mov si,offset ScrLine1
rep movsb ; Copy line to the screen
 ;rep movsb is same as the following code :
 ;mov es:di, ds:si
 ;inc si
 ;inc di
 ;dec cx
;loop until cx=0
pop cx
loop PrintBMPLoop1
ret
endp CopyBitmap1
proc CloseFile1
mov ah,3Eh
mov bx,[filehandle1]
int 21h
ret
endp CloseFile1



proc OpenFile2
; Open file
pusha
mov ah, 3Dh
xor al, al
mov dx, offset filename2
int 21h
jc openerror2
mov [filehandle2], ax
popa
ret
openerror2 :
mov dx, offset ErrorMsg2
mov ah, 9h
int 21h
popa
ret
endp OpenFile2
proc ReadHeader2
; Read BMP file header, 54 bytes
mov ah,3fh
mov bx, [filehandle2]
mov cx,54
mov dx,offset Header2
int 21h
ret
endp ReadHeader2
proc ReadPalette2
; Read BMP file color palette, 256 colors * 4 bytes (400h)
mov ah,3fh
mov cx,400h
mov dx,offset Palette2
int 21h
ret
endp ReadPalette2
proc CopyPal2
; Copy the colors palette to the video memory
; The number of the first color should be sent to port 3C8h
; The palette is sent to port 3C9h
mov si,offset Palette2
mov cx,256
mov dx,3C8h
mov al,0
; Copy starting color to port 3C8h
out dx,al
; Copy palette itself to port 3C9h
inc dx
PalLoop2:
; Note: Colors in a BMP file are saved as BGR values rather than RGB .
mov al,[si+2] ; Get red value .
shr al,2 ; Max. is 255, but video palette maximal
; value is 63. Therefore dividing by 4.
out dx,al ; Send it .
mov al,[si+1] ; Get green value .
shr al,2
out dx,al ; Send it .
mov al,[si] ; Get blue value .
shr al,2
out dx,al ; Send it .
add si,4 ; Point to next color .
; (There is a null chr. after every color.)
loop PalLoop2
ret
endp CopyPal2
proc CopyBitmap2
; BMP graphics are saved upside-down .
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
mov ax, 0A000h
mov es, ax
mov cx,200
PrintBMPLoop2 :
push cx
; di = cx*320, point to the correct screen line
mov di,cx
shl cx,6
shl di,8
add di,cx
; Read one line
mov ah,3fh
mov cx,320
mov dx,offset ScrLine2
int 21h
; Copy one line into video memory
cld ; Clear direction flag, for movsb
mov cx,320
mov si,offset ScrLine2
rep movsb ; Copy line to the screen
 ;rep movsb is same as the following code :
 ;mov es:di, ds:si
 ;inc si
 ;inc di
 ;dec cx
;loop until cx=0
pop cx
loop PrintBMPLoop2
ret
endp CopyBitmap2



;---------------------------------------------------------------------------------------
start:

    mov ax, @data
    mov ds, ax
    ; Graphic mode
    mov ax, 13h
    int 10h
    ; Process BMP file
    call OpenFile1
    call ReadHeader1
    call ReadPalette1
    call CopyPal1
    call CopyBitmap1
    ; Wait for key press
    mov ah,1
    int 21h
    cmp al , 'i'
    call CloseFile1
    je function_call
    
    ; Back to text mode
    ;mov ah, 0
    ;mov al, 2
    ;int 10h
    jmp continue
    function_call:
    call OpenFile2
    ; Graphic mode
    ; Process BMP file
    call ReadHeader2
    call ReadPalette2
    call CopyPal2
    call CopyBitmap2
    ; Wait for key press
    continue:
    mov ah,1
    int 21h
    cmp al, 'b'
    je OpenFile1
    ; Back to text mode
    mov ah, 0
    mov al, 2
    int 10h
    

‏exit:
    mov ax, 4c00h
    int 21h
END start

我在 TASM 8086 中编写一些函数已经有一段时间了,现在我想在用户输入特定字母后将图像打印到屏幕上。由于某种原因,在我输入字母后,程序没有打印图像,而是写入了错误。我尝试对我的代码进行 Turbo Debug,发现正确的值进入了

al
,并且它进入了第二个图像的函数,但不知何故出现了错误。
当我调试代码时,我看到在
openFile1
函数中,
jc openerror1
行更改为
jb #nameofthefile#openerror

有人可以帮助我吗?

我尝试在互联网和 YouTube 上寻找解释,理解这行

jc openerror1
以及为什么它在调试器中发生变化。

image debugging assembly x86-16 tasm
1个回答
0
投票

我想在用户输入特定字母后将图像打印到屏幕上。由于某种原因,在我输入字母后,程序没有打印图像,而是写入了错误。

程序中有多个错误:

  • 为了请求显示第二个位图,您有如下代码:

    cmp al , 'i'
    call CloseFile1
    je function_call
    

    CloseFile1 的调用不合适。它可能会破坏

    je
    指令试图执行操作的标志。将此指令移至正下方
    call CopyBitmap1

    call CopyBitmap1
    call CloseFile1
    
  • 第二个位图的文件名不是有效的 8.3 文件名。 DOS 可能会将

    instructions.bmp
    截断为
    instruct.bmp
    ,因此请确保 that 文件存在。但更好的是,为什么不将此文件命名为
    picture2.bmp
    。您不觉得位图的“指令”名称很奇怪吗?

  • 当处理再次显示第一个文件的请求时,您有如下代码:

    cmp al, 'b'
    je OpenFile1
    

    这是错误的,因为您要跳转到过程的开头,并且您当然知道,过程是您应该执行的代码

    call
    。结束该过程的
    ret
    指令无处可去,因为
    je
    没有将返回地址放入堆栈中。

start:
  mov  ax, @data
  mov  ds, ax
  ; Graphic mode
  mov  ax, 0013h
  int  10h
BMP1:
  call OpenFile1     ;
  call ReadHeader1   ;;
  call ReadPalette1  ;;; Why not write all of this in a single proc?
  call CopyPal1      ;;;
  call CopyBitmap1   ;;
  call CloseFile1    ;
  mov  ah, 01h
  int  21h
  cmp  al , 'i'
  jne  CONT
BMP2:
  call OpenFile2     ;
  call ReadHeader2   ;;
  call ReadPalette2  ;;; Why not write all of this in a single proc?
  call CopyPal2      ;;;
  call CopyBitmap2   ;;
  call CloseFile2    ;        <<< You forgot this one completely!
  mov  ah, 01h
  int  21h
CONT:
  cmp  al, 'b'
  je   BMP1
  ; Back to text mode
  mov  ax, 0003h
  int  10h
‏exit:

我仍然发现了更多错误,但我们不要将其变成代码审查。 例如。当您的 OpenFile 过程检测到错误时,它会在屏幕上打印一条错误消息,但是程序会愉快地继续,并且没有可用的有效文件句柄。这是灾难的根源!

© www.soinside.com 2019 - 2024. All rights reserved.