Первые n строк треугольника Паскаля (TASM) - Assembler

Узнай цену своей работы

Формулировка задачи:

Доброго вечера! Есть задача: С клавиатуры вводится N (DW). Получить первые N строк треугольника Паскаля. Задача на тему "Матрицы". Вот что я смог состряпать самостоятельно:
        lea     dx,     msg1
    outstr
    inint   N

    mov     ax,     N
    mul     dva
    mov     P1,     ax          ;P1 = 2*N
    add     ax,     2
    mov     p2,     ax          ;p2 = 2*n + 2
    
    mov     cx,     N
    xor     bx,     bx
BEG:
    mov     A[bx],  1
    add     bx,     p1
    loop    BEG                                       ;здесь заполняются единицами элементы первого столбца
    
    mov     cx,     N
    xor     bx,     bx
    
BEG10:
    mov     A[bx],  1
    add     bx,     p2                ;здесь заполняются единицами диагональными элементами
    loop    BEG10
    
;
;for i:=2 to N do
;    for j:=1 to i-1 do
  ;  a[i,j]:=a[i-1,j-1]+a[i-1,j];

; Это паскалевский эквивалент вложенных циклов
 
    xor     bx,     bx
    mov     cx,     N
    dec     cx
    mov     I,      2
    
FORI:
    push    cx
    mov     J,      1
    mov     cx,     I
    dec     cx
    
FORJ:
    mov     ax,     I
    sub     ax,     2
    mul     n
    add     ax,     j
    sub     ax,     2
    mul     dva
    mov     bx,     ax
    mov     dx,     A[bx]                    ;Здесь подсчитывается a[i-1,j-1]
 
    mov     ax,     I
    sub     ax,     2
    mul     N
    add     ax,     j
    dec     ax
    mul     dva
    mov     bx,     ax
    add     dx,     A[bx]                           ;Здесь подсчитывается  a[i-1,j-1]+a[i-1,j]
 
    mov     ax,     I
    dec     ax
    mul     n
    add     ax,     j
    dec     ax
    mul     dva
    mov     bx,     ax
    mov     A[bx],  dx                                   ;a[i,j] := a[i-1,j-1]+a[i-1,j]
    inc     J
    loop    FORJ
    pop     cx
    inc     I
    loop    FORI
;=================================================================================
    
    xor     bx,     bx
    mov     cx,     N
    
BEG1:
    push    cx
    mov     cx,     N
                                                                     ;Это просто вывод в виде матрицы
BEG2:
    outint  A[bx],4
    add     bx,     2
    loop    BEG2
    newline
    pop     cx
    Loop    BEG1
По поводу inint, outstr, newline - это наши "шаблонные" процедурки, которые выдали в университете. inint - считывает с клавиатуры число размером в слово outstr - выводит строку, расположенную в dx newline - переход на следующую строку Программа, по идее, должна выводить треугольник паскаля, но выводит матрицу со всеми нулевыми элементами, кроме диагональных. На диагоналях остаются единицы. Помогите, пожалуйста, доделать ее.
Видимо встал не стой ноги и начал писать какую-то ахинею. Переписал без всяких i и j. Вот работающий код:
    lea     dx,     msg1
    outstr
    inint   N

    mov     ax,     N
    mul     dva
    mov     P1,     ax          ;P1 = 2*N
    add     ax,     2
    mov     p2,     ax          ;p2 = 2*n + 2
    
    mov     cx,     N
    xor     bx,     bx
BEG:
    mov     A[bx],  1
    add     bx,     p1          ;заполняем элементы первого столбца единицами
    loop    BEG
    
    mov     cx,     N
    xor     bx,     bx
    
BEG10:
    mov     A[bx],  1
    add     bx,     p2          ;заполняем диагональные элементы единицами
    loop    BEG10
    
    mov     cx,     N
    sub     cx,     2
    xor     si,     si
    mov     bx,     p2          
    add     bx,     p1          ;bx = 4*N+2 - переход на первый элемент в матрице, который требует обработки
    mov     di,     bx          ;Вспомогательное приращение
    mov     gr,     1           ;Счетчик числа итераций для внутреннего цикла
 
CKL1:                           ;for i:= 2 to N
    push    cx
    mov     cx,     gr          ;for j:= 1 to gr
    
CKL2:
    mov     si,     bx          
    sub     si,     p2
    mov     dx,     a[si]       ;dx = a[i-1,j-1]
    
    mov     si,     bx
    sub     si,     p1
    add     dx,     a[si]       ;dx = a[i-1,j-1]+a[i-1,j]
    
    mov     a[bx],  dx          ;a[i,j] = dx
    add     bx,     2
    loop    CKL2
    pop     cx
    add     di,     p1          ;di = di + 2*n
    mov     bx,     di          ;таким образом осуществляется переход на следующий элемент, требующий обработки
    inc     gr
    loop    CKL1

;=================================================================================
    
    xor     bx,     bx
    mov     cx,     N
    
BEG1:
    push    cx
    mov     cx,     N
    
BEG2:
    outint  A[bx],4
    add     bx,     2           ;Вывод в виде матрицы
    loop    BEG2
    newline
    pop     cx
    Loop    BEG1
Всем спасибо!

Решение задачи: «Первые n строк треугольника Паскаля (TASM)»

textual
Листинг программы
.model small
 
.stack 100h
 
.data
        Nmax    equ     18              ;максимальное значение N, при котором все значения
                                        ;треугольника Паскаля не превышают ёмкости 16-разрядной перемменной
        N       dw      17              ;количество выводимых строк
        A       dw      Nmax dup (?)    ;текущая (выводимая) строка треугольника Паскаля
        elSize  equ     2               ;размер элемента массива
        CrLf    db      0Dh, 0Ah, '$'   ;символы перевода строки
 
.code
 
main    proc
        mov     ax,     @data           ;begin
        mov     ds,     ax
 
        cmp     N,      Nmax            ;  if N > Nmax then
        jbe     @@ShowTriangle
        mov     N,      word ptr Nmax   ;    N := Nmax;
@@ShowTriangle:
 
        mov     A[0],   word ptr 1      ;  a[1] := 1;
        mov     cx,     N               ;  for i := 1 to n do
@@For_I:
        mov     bx,     0               ;    tmp2 := 0;
        lea     si,     [A]             ;    for j := 1 to i do
        push    cx
        mov     ax,     N
        sub     ax,     cx
        inc     ax
        mov     cx,     ax
        @@For_J:                        ;    begin
 
                mov     ax,     [si]    ;      tmp1 := a[j];
                add     bx,     ax      ;      a[j] := tmp2 + a[j];
                mov     [si],   bx
                xchg    bx,     ax      ;      tmp2 := tmp1;
 
                call    Show_AX         ;      Write(a[j]: 10);
                call    WriteSpace
 
                add     si,     elSize  ;    end;
                loop    @@For_J
        pop     cx
 
        call    NewLine                 ;    writeln;
        loop    @@For_I                 ;  end;
 
        ;завершение программы
        mov     ax,     4C00h           ;end.
        int     21h
main    endp
 
; выводит знаковое 16-разрядное число из регистра AX на экран
; входные данные:
; ax - число для отображения
Show_AX proc
        push    ax
        push    bx
        push    cx
        push    dx
        push    di
 
        mov     cx,     10      ; основание системы счисления
        xor     di,     di      ; di - кол. цифр в числе
 
@@Conv:
        xor     dx,     dx
        div     cx              ; dl = num mod 10
        add     dl,     '0'     ; перевод в символьный формат
        inc     di
        push    dx              ; складываем в стек
        or      ax,     ax
        jnz     @@Conv
        ; выводим из стека на экран
@@Show:
        pop     dx              ; dl = очередной выводимый символ
        mov     ah,     2       ; ah - функция вывода символа на экран
        int     21h
        dec     di              ; повторяем пока di<>0
        jnz     @@Show
 
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
Show_AX endp
 
; Вывод на экран одного пробела
; входные данные:
; - нет
WriteSpace      proc
        push    ax
        mov     al,     ' '
        int     29h
        pop     ax
        ret
WriteSpace      endp
 
; Вывод на экран одного перевода строки
; входные данные:
; - нет
NewLine proc
        push    ax
        push    bx
        push    cx
        mov     ah,     09h
        lea     dx,     [CrLf]
        int     21h
        pop     cx
        pop     bx
        pop     ax
        ret
NewLine endp
 
end     main

Объяснение кода листинга программы

  1. Объявляются переменные:
    • Nmax с 18
    • N с 17
    • A с пустыми 18-разрядными значениями
    • elSize с 2
    • CrLf с символами перевода строки
  2. Сравнивается значение переменной N с Nmax. Если N больше Nmax, то значение N заменяется на Nmax.
  3. В первый элемент массива A записывается значение 1.
  4. Устанавливается значение cx равным N.
  5. Начинается цикл от 0 до N:
    • Устанавливается bx в 0.
    • Перебираются все элементы массива A от 1 до i:
      • Значение текущего элемента массива A (a[j]) записывается в ax.
      • bx прибавляется к ax и результат записывается обратно в a[j].
      • Обмен значениями между bx и ax.
      • Выводится значение ax.
      • Выводится пробел.
    • Выводится перевод строки.
  6. Программа завершается.

Оцени полезность:

12   голосов , оценка 4.083 из 5
Похожие ответы