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
以及为什么它在调试器中发生变化。
我想在用户输入特定字母后将图像打印到屏幕上。由于某种原因,在我输入字母后,程序没有打印图像,而是写入了错误。
程序中有多个错误:
为了请求显示第二个位图,您有如下代码:
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 过程检测到错误时,它会在屏幕上打印一条错误消息,但是程序会愉快地继续,并且没有可用的有效文件句柄。这是灾难的根源!