Turbo assembler language cursor position, offset

后端 未结 1 1221
暖寄归人
暖寄归人 2021-01-25 09:28

We have given an instruction to make the the text CSC 112.1 to be centered. I used DB instruction and offset. This is my code

.model small
.stack
.data

c    db         


        
1条回答
  •  失恋的感觉
    2021-01-25 10:05

    If all the characters are defined same way as that C, then the cursor set is just setting correct starting line, but any 13,10 new line will reset cursor to start of next line.

    Also the DOS end line is 13,10, not 10,13.

    mov ah,02h                           
    mov bh,00
    mov dx,043h
         ; set the cursor position where "04 is y coordinate"
         ; and "3 is x coordinate"
    int 10h
    

    About this, the cursor position should be in DH = row, DL = column. But 43h isn't column=3, row=4. It's column 67, row=0. To load DH=4, DL=3 you would have to do mov dx,403h or to have it more nicely byte vs byte mov dx,0403h In hexadecimal formatting single digit = 4 bits, so two digits = 8 bits (one small register). "43h" covers just single register (DL), DH is then 00h. Or if you don't get the idea of hexadecimal 1 digit = 4 bits, then you can use mov dx,3 + 4*256 (the higher byte is *256 value).

    If you want to output such letter on certain position, you will have to change the definition, to NOT include newline characters. I.e.:

    c label byte
        db "  лллл  "
        db " лллллл "
        db "лл    лл"
        db "лл      "
        db "лл      "
        db "лл      "
        db "лл      "
        db "лл      "
        db "лл      "
        db "лл    лл"
        db " лллллл "
        db "  лллл  "
    

    And output it per char, 8x12 times, not with ah=9 as single string.

    And as your letter is 8 chars wide, and with single printable character, you can actually store those data as bits, i.e.

    ; C letter, 8x12 bitmask
    c   db  03Ch, 07Eh, 0C3h, 0C0h, 0C0h, 0C0h
        db  0C0h, 0C0h, 0C0h, 0C3h, 07Eh, 03Ch
    

    This will break if you want more than 8 characters ("dots") per line, like I'm afraid your "number" definition does use, but you can build it from separate digits, but then you would need proportional font, i.e. to add one more value ahead of bitmask, defining "width" of glyph... let's do that, bump it to 16 bit values plus proportional/size info:

    ; C letter, proportional width + 16x12 bitmask
    c   dw  0C09h    ; width is 9 dots, height is 12 lines
        dw  03Ch, 07Eh, 0C3h, 0C0h, 0C0h, 0C0h  ; 16x12 bitmask
        dw  0C0h, 0C0h, 0C0h, 0C3h, 07Eh, 03Ch
    

    And I finally "mirrored" the bit data, so the left-most dot on screen is in lowest bit (which is "right-most" in binary/hexadecimal), so letter "C" is defined in bitmask like "Ɔ". And I added some filled squares and spaces to verify the print routine:

    ; file: BIGLETER.ASM
    ; author: Peter Ped7g Helcmanovsky, (C) 2017
    ; license: CC0 (public domain)
    ; builded with TASM v4.1, TLINK v5.0 under dosbox v0.74 by commands:
    ;   tasm /m5 /w2 /t /l bigleter
    ;   tlink bigleter.obj
    
    .model small
    .stack
    .data
    
    ; C letter, proportional width + 16x12 bitmask
    ; bitmask is "mirrored", the bottom (right) bit goes out first
    ; (left side of letter)
    c   dw  0C0Ah   ; width is 10 dots (8 dots have pixels), height is 12 lines
        dw  03Ch, 07Eh, 0C3h, 003h, 003h, 003h  ; 16x12 bitmask
        dw  003h, 003h, 003h, 0C3h, 07Eh, 03Ch
    
    square12x12 LABEL WORD
        dw  0C0Ch   ; width is 12 dots, height is 12 lines
        dw  0FFFh, 0FFFh, 0FFFh, 0FFFh, 0FFFh, 0FFFh  ; 16x12 bitmask
        dw  0FFFh, 0FFFh, 0FFFh, 0FFFh, 0FFFh, 0FFFh
    
    space2d LABEL WORD
        dw  0C02h   ; width is 2 dots, height is 12 lines
        dw  12 DUP (0)      ; 16x12 bitmask
        ; (12 lines to clear screen over full common letter height)
    
    space1d LABEL WORD
        dw  0C01h   ; width is 1 dot, height is 12 lines
        dw  12 DUP (0)      ; 16x12 bitmask
        ; (12 lines to clear screen over full common letter height)
    
    .286
    .code
    
    start:
        mov     ax,@data
        mov     ds,ax
        mov     ax,3        ; ah=0, al=3 => VGA text mode 80x25
        int     10h         ; (expensive "clear screen")
        ; print 2x big C at specific position
        mov     dx,0604h    ; row=6, column=4 starting position
        mov     si,OFFSET c ; data of "C" letter
        call    PrintBigLetter
        mov     si,OFFSET c ; data of "C" letter
        call    PrintBigLetter
        ; print white squares and different type of spaces
        ; (to test print routine well, including proportional feature)
        mov     si,OFFSET square12x12 ; data of filled square 12x12
        call    PrintBigLetter
        mov     si,OFFSET space2d     ; data of 2 dots "space"
        call    PrintBigLetter
        mov     si,OFFSET square12x12 ; data of filled square 12x12
        call    PrintBigLetter
        mov     si,OFFSET square12x12 ; data of filled square 12x12
        call    PrintBigLetter
        mov     si,OFFSET space1d     ; data of 1 dot "space"
        call    PrintBigLetter
        mov     si,OFFSET square12x12 ; data of filled square 12x12
        call    PrintBigLetter
    
        ; return to DOS with exit code 0
        mov     ax,4c00h
        int     21h
    
    ; in: dh:dl = row:column, ds:si = letter definition
    ; out: dh:dl = row:column adjusted for next letter
    ; modifies: ax, bx, cx, si, di (basically ALL except dx and bp)
    PrintBigLetter PROC
        mov     cx,[si]     ; ch = line count, cl = column size
        add     si,2
        ; store next letter position on stack
        add     dl,cl
        push    dx
        sub     dl,cl       ; restore position back for this letter
    PBL_row_loop:
        ; set cursor to start of next line
        mov     ah,2
        xor     bh,bh
        int     10h         ; dh:dl = row:column to set (left dot on line)
        ; load "mirrored" bitmask and prepare for printing line
        mov     di,[si]     ; di = bitmask of line
        add     si,2
        mov     ah,0Eh      ; int 10h 0E service
        ; print CL-many dots on screen
        push    cx
    PBL_dot_loop:
        mov     al,' '      ; space
        shr     di,1        ; bottom bit into CF
        jnc     PBL_dot_empty
        mov     al,0DBh     ; 0xDB = '█' filled rectangle character
    PBL_dot_empty:
        ; ah=0E, al=dot_char, bh=0, bl=? => ready to call int 10h
        int     10h         ; print single "dot" of char
        dec     cl          ; print column-size many dots
        jnz     PBL_dot_loop
        pop     cx
        ; move to next line
        inc     dh          ; next row
        dec     ch
        jnz     PBL_row_loop; CH-many rows
        pop     dx          ; set dx to position of next letter
        ret
    ENDP
    
    END start
    

    I commented source extensively, so hopefully the mechanics of how the bitmask data are printed is understandable.. if not, try debugger first (to watch how values evolve in the registers inside the print loop), if it still confusing, don't hesitate to ask here.

    0 讨论(0)
提交回复
热议问题