膜拜大牛!

授人以渔,不授人以鱼。
2012-10-06 12:32
2012-10-06 14:21
2012-10-06 14:32
2012-10-06 14:46
2012-10-06 17:04
2012-10-06 17:07
程序代码:;#Mode=DOS
;MASMPlus 单文件代码模板 - 纯 DOS 程序
;--------------------------------------------------------------------
;单个文件需要指定编译模式,否则默认是EXE方式,在系统设置中可以设置默认是DOS还是Windows.
;编译模式自带了DOS/COM/CON/EXE/DLL/LIB这几种,如果有必要,可以更改ide.ini添加新的编译模式
;当然,更好的是创建为一个工程.更方便及易于管理,使用方法:按Ctrl多选->创建工程.必须有多个文件
assume cs:code, ds:data, ss:stack
stack segment
db 128 dup(?)
stack ends
data segment
prompt db '16 lines of Left angle Yang Hui triangle: ', 0dh, 0ah, '$'
endStr db 0dh, 0ah, 'Press any key to continue', '$'
last dw 300 dup (0)
next dw 300 dup (0)
store db 10 dup(?)
data ends
code segment
start: ;; 初始化段寄存器
mov ax, stack
mov ss, ax
mov sp, 128
mov ax, data
mov ds, ax
;; 输出提示
lea dx, prompt
mov ah, 09h
int 21h
;; 确定顶部位置
mov dh, 1
mov ax, 160
mul dh
mov bx, ax
add bx, ax
;; 关联显存
mov ax, 0b800h
mov es, ax
;; 循环处理三角中的每个数值 放入显存中
;; 行列都从0下标开始
mov cx, 15 ; 循环13次 处理除首行外的其他行
mov bp, 2 ; bp/2相当于一行的最大列
mov last[0], 1 ; 输出0行0列
mov es:[bx + 6], 31h
mov es:[bx + 6 + 1], 2
add bx, 160
Set: push cx ; cx压栈 便于内循环
mov dx, 2 ; dx/2相当于内循环的列数
mov next[0], 1 ; 输出dx/2行0列
mov es:[bx + 6], 31h
mov es:[bx + 6 + 1], 2
dis: cmp dx, bp ; 比较内循环的自己列与最大列
je SetOne ; 相等就置1
; 按规律处理下一行与上一行的值
; 即C语言中的 a[i][j] = a[i - 1][j - 1] + a[i - 1][j]
; 即next[di] = last[di] + last[di - 2]
mov di, dx
mov ax, last[di]
dec di
dec di
add ax, last[di]
inc di
inc di
mov next[di], ax
mov ax, next[di]
; 转到BCD码处理 将一个数的千 百 十 个 位分别放入对应的显存
call TurnToBCD
inc dx
inc dx
jmp dis
SetOne: mov si, dx
mov next[si], 1
mov ax, next[si]
call TurnToBCD
;; 计算出next 后将其复制到last中 便于下次循环
push di
mov cx, dx
mov di, 2
SetOK: mov ax, next[di]
mov last[di], ax
inc di
inc di
loop SetOK
pop di
;; cx 出栈对应于Set循环 bp 加2 对应于dx 加2
;; bx 加 160即显存换行
pop cx
inc bp
inc bp
add bx, 160
loop Set
;; 设置光标 便于输出press any key to continue
mov ah, 2
mov bh, 0
mov dh, 18
mov dl, 0
int 10h
lea dx, endStr
mov ah, 09h
int 21h
;; 查看结果 返回DOS
mov ah, 01h
int 21h
mov ah, 4ch
int 21h
TurnToBCD: ;; 分解一个数的千 百 十 个 位分别放入对应的显存
push bx
push cx
push dx
push si
push di
push ax
;; 确定一个数字占5个位置的显存
mov ax, dx
mov dl, 5
mul dl
mov di, ax
pop ax
;; 个位
mov dx, 0
mov cx, 10
div cx
mov cx, dx
add cl, 30h
mov store[0], cl
;; 十位
mov dx, 0
mov cx, 10
div cx
add dx, 30h
mov store[1], dl
;; 百位
mov ah, 0
mov cl, 10
div cl
add ah, 30h
mov store[2], ah
;; 千位
mov ah, 0
mov cl, 10
div cl
add ah, 30h
mov store[3], ah
;; 输出到对应显存 前导为0则不输出
;; 在这里有个疑问 也就是显存的输出必须从低到高输出
;; 若是从高到低则前面的数据将被覆盖 只能显示最后一位 为什么?
mov cl, store[3]
cmp cl, 30h
jz ok
mov es:[bx + di + 2], cl
mov es:[bx + di + 3], 2
mov cl, store[2]
mov es:[bx + di + 4], cl
mov es:[bx + di + 5], 2
mov cl, store[1]
mov es:[bx + di + 6], cl
mov es:[bx + di + 7], 2
mov cl, store[0]
mov es:[bx + di + 8], cl
mov es:[bx + di + 9], 2
jmp OK3
ok: mov cl, store[2]
cmp cl, 30h
jz ok1
mov es:[bx + di + 4], cl
mov es:[bx + di + 5], 2
mov cl, store[1]
mov es:[bx + di + 6], cl
mov es:[bx + di + 7], 2
mov cl, store[0]
mov es:[bx + di + 8], cl
mov es:[bx + di + 9], 2
jmp OK3
ok1: mov cl, store[1]
cmp cl, 30h
jz ok2
mov es:[bx + di + 6], cl
mov es:[bx + di + 7], 2
ok2: mov cl, store[0]
mov es:[bx + di + 8], cl
mov es:[bx + di + 9], 2
OK3: pop di
pop si
pop dx
pop cx
pop bx
ret
code ends
end start
2012-10-06 17:09
2012-10-06 19:46
2012-10-06 19:47



2012-10-06 20:00