这是我正在做的一个粗略的、wip 的爱好项目,只是为了在 dos 中打印简单的 16 色 BMP。在对此进行修补时,我遇到了一个意外错误,我一直无法找到有关该错误的信息。
每当将line_len 移动到 dx的行被注释掉,或者当 dx 被 ax 替换时,相关错误就会消失。
new_line:
mov dx,[line_len] ;;restock on pixels
sub cx,[line_pad_len] ;;decrement cx by the padlen -1 to skip the padding.
add bx,[line_pad_len] ;;increment read address.
inc bx
loop process_loop ;;return to loop and decrement.
读取的错误(尽管确切的数字会发生变化,我认为这是自然的)
Invalid Opcode at EEAf 2D00 0217 0000 [... rest is zeroes ]
Invalid Opcode at 0013 0000 0202 0000 0013 0100 0002 0001 756E 6573 0864 0607 0405
Invalid Opcode at FECB 118A 0202 118A 189C 0000 4D4E 0000 [...]
并随后停止 FreeDOS。当对此运行调试并逐步执行时,我能读到的最后一个是(第一个)LOOP 助记符,通常它会跳到循环中的第一个更改。(据我所知。)
不幸的是,我是 DOS 和 Assembly 的新手,并且无法使用此信息找到解决方案。如果我用 AX 替换 DX,错误就会消失,但我宁愿尝试了解为什么会出现此错误,以便将来避免它。
下面的 bmp->bin 转换器的完整源代码。
org 100h
segment .code
mov ax,3d00h ;;OPEN FILE WITH 00 ACCESS. (READ ONLY)
mov dx,filename
int 21h
jc exit ;;C FLAG MEANS ERROR.
mov bx,ax ;;GET FILE HANDLE
mov ax,3f00h ;;read file.
mov cx,400h ;;1024byte buffer available.
mov dx,file_buffer ;;address to the buffer.
int 21h
jc exit ;;C etc.
mov cx,ax ;;Move read bytes into cx.
mov ax,3e00h ;;close file
int 21h
jc exit
;;confirm_file:
cmp word [file_buffer],4d42h
jnz exit_bmp ;;THIS IS NOT A BMP FILE.
mov dx,00h
mov ax, word [file_buffer+0022h]
div word [file_buffer+0016h]
dec ax
mov [line_pad_len],ax
mov dx, word [file_buffer+0012h] ;;get width of image in pixels.
cmp dx,0050h ;;check if it's too wide for our screen.
;;jmp if it is.
mov [line_len],dx
mov bx, word [file_buffer+000ah] ;;get offset of bmp array.
mov cx, word [file_buffer+0022h] ;;get size of pixel array + padding
process_loop: ;;WE WANT 16 COLOUR BMP. 2PX/BYTE. LEFTMOST PX MOST SIGNIFICANT NIBBLE.
mov al,[file_buffer+bx] ;;GET FIRST BYTE OF PIXEL ARRAY.
inc bx ;;INCREMET OUR FILE READ LOCATION.
dec dx
jbe new_line ;;if we are out of line, skip back.
mov ah,al ;;copy al into ah for safekeeping
shr ah,04h ;;ah shifted left 4bit. high nibble should be 0
and al,0fh ;;high nibble zeroed.
;;WRITE NEW DATA TO BUFFER. (STILL UPSIDE DOWN)
mov [outp_buffer+di],ah ;;write ax
inc di
mov [outp_buffer+di],al ;;write al
inc di
loop process_loop ;;DECREMENT CX LOOP
jmp write_file
new_line:
mov dx,[line_len] ;;restock on pixels
sub cx,[line_pad_len] ;;decrement cx by the padlen -1 to skip the padding.
add bx,[line_pad_len] ;;increment read address.
inc bx
loop process_loop ;;return to loop and decrement.
write_file: ;;WARNING! THIS WILL DESTROY THE FILE IT WRITES TO.
mov ah,3ch ;;CREAT FILE
mov dx,newfile ;;PTR TO FILENAME
mov cx,0000h ;;FLAGS
int 21h
jc exit
mov bx,ax ;;file handle.
mov ah,40h ;;write to our file
mov cx,di ;;di should have bytes written.
mov dx,outp_buffer ;;get pointer to output buffer.
int 21h
jc exit ;;did we fail?
mov ah,3eh ;;Close our file.
int 21h
exit:
mov ah,4ch
int 21h
exit_bmp:
mov ax,4c66h
int 21h
segment .data
filename: db "IN.BMP",00h
line_len: dw 0000h
newfile: db "OUT.BIN",00h
line_pad_len: dw 0000h
segment .bss
file_buffer: resb 1024 ;;FIGURE OUT BETTER WAY TO DO LEN.
outp_buffer: resb 1024 ;;FIGURE OUT BETTER STUFF.