Сборка x86: мне нужно запрограммировать функцию Аккермана - PullRequest
2 голосов
/ 14 марта 2012

Мне нужно запрограммировать функцию Аккермана.Это то, что я имею до сих пор:

    .model small
;
    extrn   putstrng:far
    extrn   newline:far
    extrn   getdec$:far
    extrn   putdec$:far
; 
;
    .stack 1024                  
;
    .const


    .data

    .code
    assume ds:dgroup
;
debut:  mov     ax, seg dgroup     
    mov     ds, ax
    mov     es, ax
;

    mov     ax,2   ; value of N
    mov     bx,ax
    mov     ax,2 ; Value of M
    mov     dx,ax
    mov     cx,0

    push    dx
    push    bx

    call ackermann

    pop     bx
    pop     dx

    MOV ax, 0
    MOV ax, cx
call    putdec$
call    newline


    mov     ax, 4c00h          
    int     21h

ackermann   proc far C uses cx

    mov dx, [bp+6] 
    mov bx, [bp+4]
    cmp bx, 0
    JE firstCase
    cmp dx, 0
    JE secondCase
    dec dx
    push dx
    push bx
    CALL ackermann
    pop bx
    pop dx
    dec bx
    push dx
    push bx
    CALL ackermann
    pop bx
    pop dx
    ret


firstCase:
    MOV cx, dx
    inc cx
    ret


secondCase:
    DEC bx
    push dx
    push bx
    call ackermann
    pop bx
    pop dx
    ret

ackermann endp

    end     debut

Что бы я ни указывал для значения N или M, я всегда получаю ответ 0. Я думаю, я знаю почему.Эта часть:

MOV ax, 0
MOV ax, cx
call    putdec$
call    newline

, вероятно, неправильно, но я не знаю, что с этим делать.

Любая помощь будет принята с благодарностью.

Спасибо.

1 Ответ

5 голосов
/ 14 марта 2012

Если предположить, что ваша функция Аккермана действительно работает и оставляет свой результат в регистре cx, а putdec$ печатает значение в регистре ax, то в этом сегменте кода нет абсолютно ничего плохоговы показали.

Он сначала загружает ноль в ax, но затем заменяет его на cx.

Следовательно, ваша проблема связана с одним из:

  • putdec$ не печатает ax.
  • ваша функция Ackermann не работает так, как вы ожидаете.
  • ваша функция Ackermann не возвращает свое значение в cx.

Первый шаг - запустить ваш отладчик и установить точку останова в инструкции mov ax, 0 - это скажет вам, какое значение есть в cx (и других регистрах), чтобы проверить, работает ли функция Аккермана.

Тогда вам, возможно, придется вернуться и выполнить пошаговый пошаговый просмотр функции, сравнивая ее с тем, что вы ожидаете на каждом этапе, с некоторыми бумагами и карандашами.


С небольшимстатического кодаанализ и быстрое изучение того, для чего на самом деле предназначена эта функция Аккермана :-), я могу различить следующее:

В одном я не уверен, что вы правы (если вы используете Википедиюопределение функции Аккермана здесь ) - второй случай.В нем говорится, что:

         /  n + 1             if m = 0
A(m,n) = |  A(m-1,1)          if m > 0 and n = 0
         \  A(m-1,A(m,n-1))   if m > 0 and n > 0

Ваш второй код дела уменьшается bx/m, как ожидается, но оставляет dx/n в одиночку, а не устанавливает его в единицу.

В вашем третьем случае (хотя яне присматривался) вы вызываете функцию дважды, но нигде не видно передачи cx, результата первого внутреннего вызова A(), ни в один из регистров, помещенных в стек для внешнего вызова,Это был бы важный шаг в вычислении вложенной функции, такой как A(x,A(y,z)).

Вместо этого ваш внешний вызов, похоже, использует некоторые вариации оригинальных значений.

Тедва полезных указателя должны стать хорошим началом для вас, отточить ваши навыки отладки и стать лучшим разработчиком: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...