问题
Good afternoon, I'm trying to show on screen an array of strings with GUI Turbo Asembler TASM, the problem that I can not show the all strings only the first. If someone can help me correctly display the strings on the screen and move through that array, very grateful-
This an example in Borland C++
Example
This actually in TASM:
Program in tasm
the code is the following.
.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
回答1:
Hmm.. I decided to write somewhat advanced version of the display board... I know the pure-code answers are not good ones, but I added many comments into the code to make it more clear, how it works.
Some hints about concepts used:
I'm writing directly into VGA text video memory, avoiding BIOS/DOS services (they are slow and cumbersome to use in cases like drawing game board).
The board
data contain not only letters, but the top bit (80h
value) of each "letter" is used as used/unused marker. The drawing routine will change the colour of letter based on the value of this bit.
I.e. value 41h
in board will work as "unused A", and value 41h + 80h = 0C1h
will work as "used A".
Unused/used letters have light_magenta/white colour, being calculated from the used bit and exploiting also the 40h bit of letter ASCII value.
(digits would have bright_red/yellow colours, as '0' = 30h
, so ASCII code of digits does not contain 40h bit set = different colour calculation result).
The cursor is "drawn" + "hidden" by adding/subtracting colour to the original letter colour.
And the wall of code (tested with TASM 4.1 under dosbox
):
.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
Commands used to build exe:
REM source file has name: wordgame.asm
tasm /m5 /w2 /t /l wordgame
tlink wordgame.obj
Use Turbo debugger to single step over instructions, and watch how they affect CPU state and how they modify memory (set in Options the screen to "swap always", to make the direct video RAM writes visible on user screen (Alt+F5)). Try to understand everything, also your old code, how it works and where it had problems.
来源:https://stackoverflow.com/questions/47445256/print-into-screen-array-with-character-gui-tasm-assembly