Turbo assembler language cursor position, offset

我怕爱的太早我们不能终老 提交于 2020-01-11 11:17:10

问题


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 10,13,10,13,"  лллл  ",10,13
     db             " лллллл ",10,13
     db             "лл    лл",10,13
     db             "лл      ",10,13
     db             "лл      ",10,13
     db             "лл      ",10,13
     db             "лл      ",10,13
     db             "лл      ",10,13
     db             "лл      ",10,13
     db             "лл    лл",10,13
     db             " лллллл ",10,13
     db             "  лллл  ",10,13,"$"

.code


     mov ax,@data
     mov ds,ax


call ccall                                  ;call the procedure ccall which outputs C
call scall                                  ;call the procedure scall which outputs S
call numcall                                ;call the procedure numcall which outputs 112.1
call exit                                   ;call the procedure exit and end terminate the program


                        ccall proc          ;procedures         
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

mov ah,09h                                  ;ouputs a string
mov dx,offset c
int 21h
call delay
                        ccall endp          ;end of the procedure ccall
                        scall proc
mov ah,02h                           
mov bh,00
mov dx,04ah                                 ;set the cursor position where "04 is y coordinate" and "A is x coordinate"
int 10h


mov ah,09h                                  ;ouputs a string
mov dx,offset s
int 21h
call delay
                        scall endp          ;end of the procedure
                        numcall proc        ;procedure
mov ah,02h                           
mov bh,00
mov dx,041dh                                ;set the cursor position where "04 is y coordinate" and "1D is x coordinate"
int 10h

mov ah,09h                                  ;ouputs a string
mov dx,offset num
int 21h
call delay
                        numcall endp
                        exit proc
mov ah,4ch                                  ;terminate process
int 21h
                        exit endp

                                delay proc
mov cx,300h        
D: push cx
mov cx,0ffffh
E: loop E
pop cx
loop D
ret
                                delay endp

end

The output is this and only at the left side.

What's the reason why it doesn't show in my cursor position? And also my DB instruction is only one as an example, which is c.

Any suggestion? Need help!


回答1:


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.



来源:https://stackoverflow.com/questions/47544787/turbo-assembler-language-cursor-position-offset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!