使用字符GUI TASM组件打印到屏幕阵列中 [英] Print into screen array with character GUI TASM Assembly

查看:97
本文介绍了使用字符GUI TASM组件打印到屏幕阵列中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下午好,我试图用GUI Turbo Asembler TASM在屏幕上显示一个字符串数组,这个问题我不能只显示所有字符串.如果有人可以帮助我在屏幕上正确显示字符串并遍历该数组,非常感谢-

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-

这是Borland C ++中的一个例子

This an example in Borland C++

示例

这实际上在TASM中:

This actually in TASM:

以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

推荐答案

嗯.我决定写一些高级版本的显示板...我知道纯代码答案不是很好,但是我添加了很多对代码进行注释,以使其更清楚地了解其工作原理.

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:

我正在直接写入 VGA文本视频内存,避免使用BIOS/DOS服务(它们在绘制游戏棋盘的情况下使用起来既缓慢又麻烦.

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).

board数据不仅包含字母,而且每个字母"的最高位(80h值)都用作已用/未用标记.绘制例程将根据该位的值更改字母的颜色.

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.

即板中的41h值将用作未使用的A",而值41h + 80h = 0C1h的值将用作已使用的A".

I.e. value 41h in board will work as "unused A", and value 41h + 80h = 0C1h will work as "used A".

未使用/已使用的字母为浅洋红色/白色,是根据已使用的位计算得出的,并且还利用字母ASCII值的40h位. (数字将具有亮红色/黄色,如'0' = 30h,因此数字的ASCII码不包含40h的位集=不同的颜色计算结果).

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.

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

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

用于生成exe的命令:

Commands used to build exe:

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


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


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.

这篇关于使用字符GUI TASM组件打印到屏幕阵列中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆