汇编语言 打印杨辉三角

汇编语言 打印杨辉三角

问题出处:

http://topic.csdn.net/u/20100621/16/14d49cf2-b9fb-4d0b-8000-113f4e271fba.html?seed=770263959&r=66516303#r_66516303

 CODE SEGMENT
 ASSUME  CS:CODE,DS:CODE
 org 100h
 START: jmp begin
message db 13,10,9,’Input N(N<=10): $’
error db 13,10,9,’Data out of range!$’
begin:
 push cs
 pop ds
 mov dx,offset message
 mov ah,9
 int 21h

 call shur
 cmp bp,10
 jbe goon
 mov dx,offset error
 mov ah,9
 int 21h
 jmp exit
goon:
 mov ax,0e0dh
 int 10h
 mov al,0ah
 int 10h
push bp
 call yhsj
exit:
 mov ah,0
 int 16h
 mov ah,4ch
 int 21h
 
shur proc
push cx
push bx
xor bp,bp
mov bx,10
mov cx,2
input:
mov ah,0 ;键盘输入数据
int 16h
cmp al,0dh ;以回车结束输入
jz ok
cmp al,’0′ ;只允许输入0~9
jb input
cmp al,’9′
ja input
mov ah,0eh ;显示有效输入
int 10h
sub al,30h ;化ASCII为HEX
cbw ;字节扩展为字
xchg ax,bp
mul bx ;扩大10倍
add bp,ax ;加一位
loop input
ok:nop ;数值结果在BP中
;恢复用到的寄存器
pop bx
pop cx
ret
shur endp

; 输出杨辉三角的函数,接受一个栈上的参数N
; 输出N阶杨辉三角
yhsj:
  mov bp, sp
  mov ax, [bp+2]    ; 保存N到ax
  shr ax, 1   ; N = N / 2
  push ax
  mov ax, [bp+2]    ; 保存N到ax
  push ax
  call C; C(N, N/2)获取最后一行中间的那个值,即最大值
  call getdigit     ; 计算该最大值的长度,如252则返回3
  mov cx, ax  ; 保存最大长度到cx,用于事后格式用
  xor di, di  ; 外层循环计数di,外层循环输出每一行
  jmp cp1
up1:
  inc di; 更新di
cp1:
  cmp di, [bp+2]    ; 测试循环条件,循环N次
  jg done1
  mov ax, [bp+2]    ; 以下3句计算行前空格数 = (N-i)*cl,cl是最大长度
  sub ax, di
  mul cl
  call showspace    ; 输出行前空格
  xor si, si  ; 内存循环计数si,内层循环输出一行中的每个数
  jmp cp2
up2:
  inc si; 更新di
cp2:
  cmp si, di  ; 测试循环条件,循环di次
  jg done2
  push si
  push di
  call C; 获取该行的位于si位置的组合数,调用C(di, si)
  push ax     ; 保存该组合数
  call show   ; 输出该数
  mov ax, cx  ;┒以下3句输出数字间间隔空格,个数 = N – 1
  sub ax, 1   ;┃
  call showspace    ;┚
  pop ax;┒
  call getdigit     ;┃获取该组合数长度
  mov bx, ax  ;┃
  mov ax, cx  ;┃
  sub ax, bx  ;┃计算需要填充的空格数 = 最大长度 – 该数长度 + 1
  add ax, 1   ;┃本来应该先填充再输出数字间空格,顺序反过来是为了左对齐
  call showspace    ;┚以上打括号的2段反过来是正常的顺序
  jmp up2     ; 更新内层循环
done2:  ; 内层循环结束
  mov ah, 2   ; 以下5句实现换行
  mov dl, 13
  int 21h
  mov dl, 10
  int 21h
  jmp up1     ; 更新外层循环
done1:  ; 外层循环结束
  ret 2 ; 释放函数参数使用的栈空间

; 求组合数的递归函数,接受栈上的2个参数n, m(n > m)
; 返回C(n, m),即n选m的个数
; 算法是:
; { C(n, m) = 1 (n < m 或 m = 0)
; { C(n, m) = C(n-1, m-1) + C(n-1, m) (n > m)
; 即某位置组合数等于上一行左右两数之和
C:
  push bp
  mov bp, sp
  sub sp, 2   ; 预留一个存储位置
  mov bx, [bp+6]    ; 保存m到bx
  cmp bx, [bp+4]    ; 如果m > n 返回1
  jz L1
  cmp bx, 0   ; 如果m = 0 返回1
  jz L1
  mov ax, [bp+4]    ; 保存n到ax
  dec ax; ax = ax – 1
  dec bx; bx = bx – 1
  push bx
  push ax
  call C; 返回上一行左边的那个数
  mov [bp-2], ax    ; 保存左肩膀上的数
  mov ax, [bp+4]    ; 以下5句同理,返回上一行右肩膀上的数
  dec ax
  push [bp+6]
  push ax
  call C
  add ax, [bp-2]    ; 和左肩膀上的数相加得出该组合数
  jmp L2
L1:
  mov ax, 1
L2: 
  mov sp, bp
  pop bp
  ret 4 ; ax返回组合数

; 递归以10进制输出ax
; 方法很简单,就是求出余数,然后ax = ax / 10
; ax = 0时退出,开始逆序输出求出的各位余数
show:
  mov bx, 10
  cmp ax, 0
  jz ok1
  div bl
  push ax
  and ax, 00ffh
  call show
  pop dx
  mov dl, dh
  or dl, 30h
  mov ah, 2
  int 21h
ok1:
  ret

; 获取一个数的长度,ax为参数,如果ax = 252则返回3
; ax里是返回值
getdigit:
  mov bx, 10
  xor dx, dx
next:
  cmp ax, 0
  jle ok2
  div bl
  and ax, 0ffh
  inc dx
  jmp next
ok2:
  mov ax, dx
  ret

; 输出ax个空格,参数ax,无返回值
showspace:
  mov bx, ax
  mov ah, 2
  mov dl, ‘ ‘
nexts:
  cmp bx, 0
  jle dones
  int 21h
  dec bx
  jmp nexts
dones:
  ret

 CODE ENDS
 END START

 

 

 

 

    原文作者:杨辉三角问题
    原文地址: https://blog.csdn.net/dididu1515/article/details/5695565
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞