使用字符 GUI TASM 组件打印到屏幕阵列

Print into screen array with character GUI TASM Assembly

下午好,我正在尝试使用 GUI Turbo Asembler TASM 在屏幕上显示字符串数组,但我无法仅在第一个显示所有字符串。如果有人能帮我在屏幕上正确显示字符串并在那个数组中移动,非常感谢-

这是 Borland C++ 中的示例

Example

这实际上在 TASM 中:

Program in tasm

代码如下

.MODEL small

.STACK  100h ; reserves 256 bytes of uninitialized storage

.DATA
startX equ 35
startY equ 8
y db ?
x db ?
t1 db ?
t2 db ?
t3 db ?

zSprite db'M','M','L','E','E','N','A','E','V','E',
    db'E','R','H','O','N','G','O','S','T','R',
    db'X','X','O','T','I','R','R','A','C','A',
    db'I','S','A','P','P','O','T','A','P','S',
    db'C','C','M','L','A','A','I','Z','O','T',
    db'O','A','A','U','A','N','U','L','P','U',
    db'S','O','M','B','R','E','R','O','M','P',
    db'C','N','E','A','R','R','I','I','O','O',
    db'W','O','J','E','N','O','C','P','Z','E',
    db'A','A','Z','A','A','L','N','Y','T','D'


.386 ;enabled assembly of non privileged 80386 instructions
.CODE
start:
;set DS to point to the data segment
mov ax,@data
mov ds,ax

mov di,offset zSprite

mov y,0

l5:
cmp y,10
jl  l0
jmp l1

l0:
mov x,0

l4:
cmp x,10
jl  l2
jmp l3

l2:
mov al,startX
add al,x
mov t1,al

mov al,startY
add al,y
mov t2,al

; set cursor position at (x,y)
mov ah,02h ;set cursor position service
mov bh,00h ;page number
mov dh,t2 ;row
mov dl,t1 ;column
int 10h ;bios interrupt

mov ax,0 ;reset ax
mov al,y ;ax = y
mov bx,10
mul bx   ;ax = ax * 10
mov bx,0 ;reset bx
mov bl,x ;bx = x
add ax,bx ;ax = ax + x
mov bx,ax

; set color
mov ah,09h ;service
mov al, zSprite;character
mov bh,00h ;page number
mov bl,[bx+di] ;color
mov cx,01h ;number of times to print character
int 10h

;print symbol
mov ah, 02h  
mov dl,  zSprite
int 21h 

inc x
jmp l4

l3:
inc y
jmp l5

l1:
nop

exit:
;DOS: terminate the program
mov ah,4ch ; mov ax, 4c00h
mov al,0h
int 21h

delay PROC
pop bx

mov ax,1000d
mov dx,ax

delay1:
mov cx,ax

delay2:
dec cx
jnz delay2
dec dx
jnz delay1

push bx

ret
delay ENDP

END start

嗯..我决定写一些高级版本的显示板...我知道纯代码的答案不是很好,但我在代码中添加了很多注释以使其更清晰,如何有效。

关于所用概念的一些提示:

我正在直接写入 VGA text video memory,避免使用 BIOS/DOS 服务(它们在绘制游戏板等情况下使用起来既慢又麻烦)。

board数据不仅包含字母,而且每个"letter"的最高位(80h值)用作used/unused标记。绘图例程将根据此位的值更改字母的颜色。

即board 中的值 41h 将作为 "unused A",值 41h + 80h = 0C1h 将作为 "used A".

Unused/used 字母具有 light_magenta/white 颜色,从使用的位计算并利用字母 ASCII 值的 40h 位。 (数字会有 bright_red/yellow 颜色,如 '0' = 30h,因此数字的 ASCII 码不包含 40h 位设置 = 不同颜色计算结果)。

光标是"drawn" + "hidden"由adding/subtracting颜色到原来的字母颜色。


还有代码墙(在dosbox下使用TASM 4.1测试):

.MODEL small

.STACK  100h ; reserves 256 bytes of uninitialized storage

.DATA

BOARD_SIZE_X    EQU     10
BOARD_SIZE_Y    EQU     10
START_X         EQU     35
START_Y         EQU     8
CURSOR_COLOR    EQU     0B0h     ; add "blink" + cyan background

board LABEL BYTE
    DB "MMLEENAEVE"
    DB "ERHONGOSTR"
    DB "XXOTIRRACA"
    DB "ISAPPOTAPS"
    DB "CCMLAAIZOT"
    DB "OAAUANULPU"
    DB "SOMBREROMP"
    DB "CNEARRIIOO"
    DB "WOJENOCPZE"
    DB "AAZAALNYTD"

cursor_x        db  5
cursor_y        db  7

.386
.CODE
start:
    ;set DS to point to the data segment
    mov     ax,@data
    mov     ds,ax   ; ds = data segment
    mov     ax,0B800h
    mov     es,ax   ; es = text VRAM segment for direct VRAM writes

    ; fake some characters being "used" to test drawing code
    or      BYTE PTR [board+34],80h     ; mark the "POT" word
    or      BYTE PTR [board+35],80h     ; on fourth line in middle
    or      BYTE PTR [board+36],80h

    call    clear_screen
    call    draw_board
    mov     dl,CURSOR_COLOR
    call    draw_cursor

    ; wait for keystroke
    xor     ah,ah
    int     16h

    ; fake "move cursor"
    mov     dl,-CURSOR_COLOR        ; hide cursor on old position
    call    draw_cursor
    inc     BYTE PTR [cursor_x]     ; move it up+right
    dec     BYTE PTR [cursor_y]
    mov     dl,CURSOR_COLOR         ; show cursor on new position
    call    draw_cursor
    ; (other option would be to redraw whole board)

    ; wait for keystroke before exit
    xor     ah,ah
    int     16h
    ; exit to DOS
    mov     ax,4C00h
    int     21h

; sets whole text video RAM to white "space" with red background
; modifies ax, cx, di, assumes es=B800
clear_screen PROC
    xor     di,di   ; B800:0000 target address
    mov     ax,' ' + 4Fh*256 ; white space on red background
    mov     cx,80*25
    rep stosw       ; fill up video RAM with that
    ret
ENDP

; redraws whole board to the video RAM, marks "used" characters too
; modifies ax, cx, dx, si, di, assumes ds=@DATA, es=B800
draw_board PROC
    mov     si,OFFSET board ; si = address of first letter of board
    ; di = offset of starting position in video RAM
    ; 2 bytes per char (char+color), 80 chars (160B) per line
    mov     di,(START_Y*80 + START_X)*2
    ; output BOARD_SIZE_Y lines
    mov     dx,BOARD_SIZE_Y
board_line_loop:
    ; output BOARD_SIZE_X coloured characters
    mov     cx,BOARD_SIZE_X
board_char_loop:
    lodsb           ; al = next character + used bit, advance si +1
    mov     ah,al   ; color of unused/used will be: 12 + 1 || 3 = 13 || 15
    and     al,7Fh  ; clear the top bit (used/unused): al = ASCII letter
    shr     ah,6    ; ah = 1 || 3 (80h "used" bit + 40h bit from letter code)
    add     ah,12   ; ah = 13 || 15 by "used" bit (magenda/white on black)
    stosw           ; write letter+color to VRAM es:di, advance di +2
    dec     cx
    jnz     board_char_loop ; loop till whole line is displayed
    ; move video ram pointer to start of next line
    add     di,(80-BOARD_SIZE_X)*2  ; advance to start of next line
    dec     dx
    jnz     board_line_loop ; loop till every line is displayed
    ret
ENDP

; Modifies letter color at current cursor position by adding DL
; modifies ax, di, assumes ds=@DATA, es=B800
draw_cursor PROC
    mov     al,[cursor_y]
    mov     ah,160
    mul     ah      ; ax = cursor_y * 160
    movzx   di,BYTE PTR [cursor_x] ; di = zero-extended cursor_x
    add     di,di   ; di *= 2 (cursor_x*2)
    add     di,ax   ; di += cursor_y * 160
    ; add initial board offset and +1 to address attribute only
    add     di,(START_Y*80 + START_X)*2 + 1
    add     es:[di],dl  ; modify letter color by adding DL
    ret
ENDP

END start

用于构建 exe 的命令:

REM source file has name: wordgame.asm
tasm /m5 /w2 /t /l wordgame
tlink wordgame.obj

使用 Turbo 调试器单步执行指令,观察它们如何影响 CPU 状态以及它们如何修改内存(在选项中将屏幕设置为 "swap always",使直接视频 RAM 写入在用户屏幕上可见 (Alt+F5))。尝试了解所有内容,包括您的旧代码,它是如何工作的以及哪里有问题。