问题
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