2013-10-01 2 views
1

이것은 간단한 16 색 BMP를 DOS로 인쇄하기위한 거친 작업입니다. 이것으로 땜질하는 동안 나는 예기치 않은 오류를 발견했기 때문에 정보를 찾을 수 없었습니다.DOS에서 잘못된 값으로 DX 값을 저장합니다.

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 니모닉이며, 여기서 normaly은 루프의 첫 번째 변경으로 건너 뜁니다. (내가 알 수있는 한)

불행히도, 나는 DOS와 Assembly 모두에서 초보자이며이 정보로 해결책을 찾을 수 없었다. DX를 AX로 대체하면 오류가 사라지 긴하지만이 오류가 나타나는 이유를 이해하려고 노력할 것입니다. 그래서 앞으로는 피할 수 있습니다.

아래의 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. 
+0

IN.BMP의 크기는 무엇입니까? 나는 128x96 픽셀 인 16 색 비트 맵을 사용했고, 8190 바이트의 출력 파일을 얻었다. 오류가보고되지 않았습니다 (DOSBox 사용). – Michael

+0

내 IN.BMP는 80x32입니다. 다른 크기로 이것을 읽었을 때 나는 그것을 다시 테스트했고 실패하지 않았습니다. (결과 bin이 올바르지 않습니다. bmp와 bottom-to-top 순서로 패딩을 뺀 것입니다.) 그렇지만 너비 80은 오류를 재현하는 것 같습니다. – Vivix

답변

2

난 당신의 코드에서 몇 가지 문제를 발견했습니다

DECJBE를 사용하지 마십시오. JBECF=1 or ZF=1 인 경우 점프하지만 DEC은 캐리 플래그를 수정하지 않습니다. CMP DX,50h 위의 이 캐리 플래그를 수정하므로 DX (line_len)의 값에 따라 첫 번째 반복에서 잘못된 점프를 얻을 수 있습니다. JBE을 사용하려면 DEC DX 대신 SUB DX,1을 사용해야합니다. SUB이 캐리 플래그를 수정하기 때문입니다.


루프 내부에 CX 업데이트가 잘못되었습니다.
80 * 32 픽셀의 이미지를 고려하십시오. 픽셀 배열의 크기는 80 * 32/2 == 0x500 바이트입니다. line_len은 0x50이고 line_pad_len은 0x500/0x20-1 == 0x27입니다. process_loop은 첫 번째 주사선에 대해 80 회 실행되므로 처음으로 new_line에 도달하면 CX은 0x4B0이됩니다. 그런 다음 CX다시; 이 시간은 0x27 + 1입니다. 따라서 총계에서 CX은 80 + 0x27 + 1 == 0x78 각 스캔 라인만큼 감소합니다. 0x500은 0x78로 균등하게 나눌 수 없으므로 CX은 0에 도달하는 대신 랩 어라운드하여 무한 (또는 적어도 길은 길이) 루프를 만듭니다.


상술 한 바와 같이하여 내부 루프 반복 line_len 주사선 당 횟수 (화소 당, 즉 하나의 반복 ), 및 각 반복에서 1 파일 버퍼 인덱스 (BX)를 갱신하고있다. 그러나 버퍼에는 픽셀 수의 절반 밖에 들어 있지 않습니다. 이미 내부 루프에서 BX이 증가했지만 각 스캔 라인의 끝에 line_pad_lenBX에 추가하고 있습니다.여기서 BX에 추가해야하는 것은 패딩 바이트 (있는 경우)의 번호입니다.

관련 문제