我的任务是编写一个 Intel 8086 汇编语言程序,在不使用 INT 10h 指令的情况下显示数字金字塔。结果应如屏幕截图所示:
Progr segment
assume cs:Progr, ds:dane, ss:stosik
start:
mov ax, dane
mov ds, ax
mov ax, stosik
mov ss, ax
mov ax, offset szczyt
mov sp, ax
; Clear screen
mov ax, 0B800h
mov es, ax
xor di, di
mov cx, 2000
xor ax, ax
rep stosw
mov bl, 5
mov bh, 0
mov dh, 1
mov dl, 40
mov al, 65
mov cx, 1
mov di, 24
piramida:
push cx
wiersz: mov ah, bl
shl bx, 1
add bx, dx
shl bx, 1
mov es:[bx], ax
dec cx
jnz wiersz
pop cx
inc dh
dec dl
inc al
add cx,2
inc bl
dec di
jnz piramida
mov ah, 4Ch
mov al, 0
int 21h
Progr ends
dane segment
dane ends
stosik segment
dw 100h dup(0)
szczyt Label word
stosik ends
结束开始
wiersz: mov ah, bl shl bx, 1 add bx, dx shl bx, 1 mov es:[bx], ax
这个地址计算没有意义!由于存储颜色属性的 BL 寄存器是更宽的 BX 寄存器的一部分,因此您将丢失正确的颜色信息。为什么你甚至从 BL 中检索颜色而不是从一开始就将其保留在 AH 中?是因为整个程序是基于使用
int 10h
进行字符输出的现有版本吗?我和你一样确信这一点:
mov bl, 5 ; Color mov bh, 0 ; Page mov dh, 1 ; Row mov dl, 40 ; Column ... inc dh ; Next row dec dl ; 1 column more to the left inc al ; Next ASCII add cx,2 ; Wider inc bl ; Next color
这些正是人们所期望的
int 10h
解决方案。
这里重要的教训是,您必须首先了解一段代码在做什么在修改之前它。
常规 80 x 25 文本屏幕每行使用 160 字节。您希望金字塔的顶部位于第一行的中间,因此将地址寄存器初始化为 80。稍后,为了下降一行,您将在该地址上添加 160 个字节,并再减去 2 个字节,因为每个级别也开始向左多一个字符。
一旦你正确地获得了这些地址,就真的没什么了:
mov dx, 0B800h
mov es, dx
cld
mov cx, 1
mov bx, 80
mov ax, 0541h
Next:
mov di, bx
push cx
rep stosw
pop cx
add cx, 2
add bx, 160 - 2
add ax, 0101h ; Next character and next color (SWAR-style)
cmp al, 'Y' ; A to X are to be used
jb Next
这次确保你理解代码,不要只是复制/粘贴而什么也学不到...