Turbo汇编语言光标位置,偏移量

时间:2017-11-29 03:54:58

标签: assembly dos x86-16 tasm

我们已经给出了使文本CSC 112.1居中的指令。我使用DB指令和偏移量。 这是我的代码

.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

输出是这个,只在左侧。

It only outputs like this?它之所以没有显示在光标位置的原因是什么?而且我的DB指令只有一个例子,即c。

有什么建议吗?需要帮助!

1 个答案:

答案 0 :(得分:1)

如果所有字符的定义方式与C相同,则光标设置只是设置正确的起始行,但任何13,10新行都会将光标重置为下一行的开头。

DOS端线也是13,10,而不是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

关于此,光标位置应在DH =行,DL =列中。但是43h不是column = 3,row = 4。它是第67列,行= 0。要加载DH=4, DL=3,您必须执行mov dx,403h或更好地使字节与字节mov dx,0403h在十六进制格式化单个数字= 4位,因此两位数= 8位(一个小寄存器) )。 “43h”仅涵盖单个寄存器(DL),DH则为00h。或者如果你不知道十六进制1位= 4位,那么你可以使用mov dx,3 + 4*256(高位字节是* 256值)。

如果要在特定位置输出此类字母,则必须更改定义,不包括换行符。即:

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

按字符输出,8x12次,而不是ah = 9作为单个字符串。

由于你的信件是8个字符宽,并且具有单个可打印字符,你实际上可以将这些数据存储为位,即

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

如果你想要每行超过8个字符(“点”),这会破坏,比如我害怕你的“数字”定义确实使用,但你可以用不同的数字构建它,但是你需要比例字体,即在位掩码之前再添加一个值,定义字形的“宽度”......让我们这样做,将其加到16位值加上比例/大小信息:

; 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

我最后“镜像”了位数据,因此屏幕上最左边的点位于最低位(二进制/十六进制中“最右边”),因此字母“C”在位掩码中定义为“ Ɔ”。我添加了一些填充的正方形和空格来验证打印例程:

; 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

我广泛评论了源码,所以希望如何打印位掩码数据的机制是可以理解的......如果没有,首先尝试调试器(观察值如何在打印循环内的寄存器中演变),如果它仍然令人困惑,请不要我在这里犹豫不决。