我没明白这个示例程序集有啥问题

Posted

技术标签:

【中文标题】我没明白这个示例程序集有啥问题【英文标题】:I Didn't Get Whats wrong with this exemple Assembly我没明白这个示例程序集有什么问题 【发布时间】:2020-05-03 18:16:36 【问题描述】:

我做了一个滚动bmp的简单例子 我不明白两件事:

1.为什么图片从中间开始

2.为什么屏幕上x变后中间有一条线

我真的需要帮助 因为我坚持了一个星期,我无法解决它

代码:

        IDEAL

        MODEL large
    Macro ReadBmp FileName
        mov [Lines],0
        mov [Weight],0



        mov ax,[Y]
        mov [CurrentY],ax

        mov [XScreen],0
        mov [YScreen],0


        mov dx, offset FileName  ;Mov Dx Offset Of File To Read It
        ;call ClearBuff
        call ReadToBuffer       ;Call Proc That Move Values To Buffer
        call ShowBMP

        mov ax,[CurrentY]
        mov [Y],ax
    EndM
    P386
        STACK 256

        RightDown        equ 77
        LeftDown         equ 75
        UpDown           equ 72
        DownDown         equ 80
        ScreenRam        equ 0A000h

        DATASEG
        ErrorMsg         DB 'There Is A Problem To Show The File$'
        Handle           DW ?
        File             DB 'Map.bmp',0
        Index            DD ?
        X                DW 0
        Y                DW 0
        CurrentY         DW 0
        XScreen          DW 0
        YScreen          DW 0
        Weight           DW 0
        Lines            DB 0
        ;SizeFile DD 0 
    SEGMENT BufferBmp para public  ;'DATA'  
            DB 65535 DUP(0)
    ENDS

            CODESEG   

    Start:
            mov ax, @data
            mov ds, ax

            mov ax, BufferBmp
            mov es, ax

            mov ax, 0013h
            int 10h

    Draw:           
            ReadBmp File
    lop:        

            mov ah,00
            int 16h
            cmp ah,RightDown
            je Right
            cmp ah,LeftDown
            je Left
            cmp ah,UpDown
            je Up
            cmp ah,DownDown
            je Down
            cmp ah,1
            je Exit
    jmp lop

    Right:
        add [X],5
    jmp Draw
    Left:
        sub [X],5
    jmp Draw
    Up:
        sub [Y],5
    jmp Draw
    Down:
        add [Y],5
    jmp Draw

    Exit:
            mov ax,04c00h
            int 21h

    Proc ClearBuff near
        mov si,0
        mov al,15
    NoFinish:
        mov [es:si],al
        inc si
        cmp si,65535
        jne NoFinish
    ;-----------------------------Clear Screen-----------------------------;
            mov ax,ScreenRam      
            xor di,di                           
            mov cx,320*200/2                    
            mov al,0d                           
            mov ah,0d                           
            rep stosw                           
    ;-----------------------------Clear Screen-----------------------------;
        ret
    endp
    Proc ReadToBuffer near
    ;--------------------OpenFile Use Handle--------------------;
        mov ah, 3Dh             ;INT 21 Know If Ah == 3dh He Need To Open/Create File
        mov al, 0               ;Read Only
        ;mov dx,offset FileName
        int 21h
        jc  @@Err
        mov [Handle], ax        ;Handle On ax Go To Var
    ;--------------------Copy Lines To Buffer------------------;
    ;--------------------Move Pointer To Check End Of File--------------------;
    ;   mov     ah,  42h                 ;int 21h Know That If AH == 42h He Move Pointer On File
    ;   mov     al,  02                  ;End Of File To Know Size Of A File
    ;   mov     bx, [Handle]             ;BX = file handle
    ;   xor     ecx,ecx                  ;CX:DX = offset from origin of new file position.
    ;   xor     edx,edx                  ;CX:DX = offset from origin of new file position.  
    ;   int     21h                 
    ;   jc      @@Err
    ;   ;Enter The Image Size Into A Variable
    ;   mov     [SizeFile],eax 
    ;   mov     eax,65536
    ;   mul     edx
    ;   add     [SizeFile],eax
    ;   cmp     [SizeFile],0
    ;   je     @@Err
    ;--------------------Move Pointer To Check End Of File--------------------;
    @@Lop:         
    ;--------------------Calculate index By WY+X-------------;
        mov     eax, 1920                ;Eax == 1920(Weight Of Map)
        xor     ebx, ebx                 ;ebx = 0
        mov     bx,  [Y]                 ;Bx == Y   
        mul     ebx                      ;W*Y
        xor     ebx, ebx                 ;Ebx = 0
        add     ax, [X]                  ;WY+X 
    ;--------------------Calculate index By WY+X-------------;
    ;--------------------Flip Image--------------------;
        ;mov    [index],eax              ;index == eax
        ;mov     eax,[SizeFile]          ;eax == All Byte Image 
        ;sub     eax,[index]                 ;Eax - Index
    ;--------------------Flip Image--------------------;

        mov     [index],eax              ;index == eax
        xor     edx, edx                 ;edx = 0
        mov     ebx, 65536               ;ebx = 65536
        div     ebx                      ;Dx = Remains,ax = dose
        mov     ecx,  eax                ;CX = high order word of number of bytes to move
        xor     ebx, ebx                 ;edx = 0
                                        ;CX:DX distance to move file pointer: offset is (CX * 65536) + DX

    ;--------------------Move Pointer To Read Data--------------------;
        mov     ah,  42h                 ;int 21h Know That If AH == 42h He Move Pointer On File
        mov     al,  00                  ;Current Location Plus Offset
        mov     bx, [Handle]             ;BX = file handle
                                        ;CX:DX = offset from origin of new file position. 
        int     21h                 
        jc      @@Err
    ;--------------------Move Pointer To Read Data--------------------;

    ;--------------------Read Data--------------------;

        mov     bx, [Handle]             ;BX = file handle
        mov     dx, [Weight]             ;DS:DX = pointer to read buffer
        pusha     
        push    ds
        mov     ax, BufferBmp
        mov     ds, ax
        mov     cx, 320                 ;CX = number of bytes to read---;320 = Line;
        mov     ah, 3Fh
        int     21H
        pop     ds
        popa
        jc      @@Err           
    ;--------------------Read Data--------------------;
        inc     [Lines]
        inc     [Y]                      ;Add Y To Calculate Position
        add     [Weight], 320            ;Add Weight X
        cmp     [Lines],  200            ;Check End
        jne     @@Lop

        mov     ah, 3Eh                  ;Close File
        mov     bx,[Handle]              ;BX = file handle
        int     21H
        jc      @@Err   
        ret

    @@Err:  
            mov     ax, 3                ; Set text mode
            int     10h
            mov     dx, offset ErrorMsg
            mov     ah, 09h
            int     21h                  ;Print Error
            jmp     Exit
    endp

    Proc ShowBMP near
        mov si,0                     ;Start From The Begining Of Buffer
        mov bx,0                         ;page 0
    @@Horizontal:                        
        mov ah,0Ch                       ;int 10h Know That If AH == 0Ch He Write Graphics Pixel at Coordinate
        mov al, [es:si]                  ;Color
        mov cx,[XScreen]                 ;X
        mov dx,[YScreen]                 ;Y
        int 10h
        inc si                           ;mov to next pixel
        inc [XScreen]                    ;Add X
        cmp [XScreen],320                ;Check End Line
        jne @@Horizontal
        inc [YScreen]                    ;Add Y
        mov [XScreen],0                  ;Start New Line
        cmp [YScreen],200                ;Check End Of Image
        jne @@Horizontal
    ret
    endp



    End Start

使用此图像的程序: https://drive.google.com/file/d/1T8aBZr8mtCUmQL2WKmQfklmEMfaOCklG/view?usp=sharing

【问题讨论】:

您的 ShowBMP 代码似乎假定图像为 320x200,但我从该链接下载的文件是 1920x600? BMP 将其尺寸存储在文件中。为什么不读呢?然后你可以从那里倒数,当你达到零时退出。 我想在这方面为您提供帮助,但您不喜欢我对您的previous question 关于 PCX 的回答吗? 哦,我没看到评论... 无论如何我该如何解决我的问题? :) 尺寸存储在下面 Sep 提到的 BITMAPINFOHEADER 中。 【参考方案1】:

添加斧头,[X]

在计算文件偏移量时,您忘记考虑添加 X

的进位
mov     eax, 1920                ;Eax == 1920(Weight Of Map)
xor     ebx, ebx                 ;ebx = 0
mov     bx,  [Y]                 ;Bx == Y   
mul     ebx                      ;W*Y
xor     ebx, ebx                 ;Ebx = 0
mov     bx, [X]  
add     eax, ebx   <<<< correct addition

这个 32 位数字到 CX:DX 的转换很简单:

push eax
pop  dx
pop  cx

除以 65536 没有用。 现在可以调用DOS.function 42h了。


每个 .BMP 图形文件都以包含有关图片的重要信息的标题开头。对于您的 256 色位图文件,这些是:

一个 14 字节的 BITMAPFILEHEADER 一个 40 字节的 BITMAPINFOHEADER 1024 字节可着色

然后是您需要的像素数据。这就是为什么你的文件偏移量的计算应该添加 eax, 14+40+1024

movzx   eax, word [Y]       ; Y position within bitmap
imul    eax, 1920           ; Width of bitmap
movzx   ebx, word [X]       ; X position within bitmap
lea     eax, [eax+ebx+1078] <<<< Plus offset to start of pixel data
push    eax
pop     dx
pop     cx

【讨论】:

你真的很天才,但是当x,y = 0时,它仍然从图像中间开始,为什么?我还是不明白为什么 x 有一个进位,最大的 x 是 320 @Gad 来自add ax, [X] 的进位不仅取决于X 中的值。 AX 中的内容使加法溢出! @Gad 非常感谢。我就是喜欢那颗小小的心。

以上是关于我没明白这个示例程序集有啥问题的主要内容,如果未能解决你的问题,请参考以下文章

神经网络中的训练集、验证集和测试集有啥区别?

批处理、重复和随机播放对 TensorFlow 数据集有啥作用?

验证集与测试集有啥区别?为啥要分训练集、验证集和测试集?

k-means聚类算法python实现,导入的数据集有啥要求

INTEL和AMD的CPU都有很多指令集,这个有啥用?对电脑的运行速度有影响吗?

我有一个 laravel 应用程序,它显示一个带有数据表的表格。我正在使用服务器端数据表,数据集有超过 15k 行