【问题标题】:Assembly program to add odd numbers using conditional jump使用条件跳转添加奇数的汇编程序
【发布时间】:2016-02-19 18:30:42
【问题描述】:

我有一个任务:

使用条件跳转编写汇编代码以添加以下 15 个奇数。

奇数:3、5、7、9、11、13、15、17、19、21、23、25、27、29、31

我提出了这个解决方案。我想检查一下它有什么问题...

[org 0x0100]
mov bx, num1
mov cx, 15
mov ax, 0
li:
add ax, [bx]
add bx, 2
sub cx, 1
jnz li
mov ax, 0x4c00
int 0x21
num1: dw 3, 5, 7, 9, 11, 13, 15, 17, 19, 21,23,25,27,29,31

【问题讨论】:

  • 是什么让你觉得它有问题?我觉得没问题
  • 我正在使用 AFD 来查找错误...并且代码没有在其上运行...寄存器重载类型错误将被写入它们。
  • 您的代码看起来不错。到目前为止,我从未使用过 AFD.EXE。我下载了它,并在使用 F1 的代码中运行了您的代码,以单步执行您的代码,直到 before 调用 mov ax, 0x4c00 int 0x21AX 包含 0xFF,即 255十进制。 3+5+7+9+11+13+15+17+19+ 21+23+25+27+29+31 = 255 所以我觉得不错。您在哪里看到此寄存器过载类型错误?我用 nasm -f bin testit.asm -o testit.com 组装了你的代码。然后我加载了 DOSBOX 并加载了AFD TESTIT.COM
  • 你为什么要mov ax, 0x4c00?它似乎覆盖了加法的结果。
  • @MikeCAT OP 未能提及这部分问题 解释程序的每条指令,并提供/粘贴将在 AFD 中运行的汇编和调试程序结果的快照(完整Screen Debugger) 窗口显示 AX 寄存器中执行的代码最终结果。 .看起来他们只是假设通过调试器来找到他们的 AX 值。我认为 AX 最终被破坏(或不使用)并不重要

标签: assembly nasm dos 16-bit


【解决方案1】:

这当然是一个的方法,你唯一需要注意的是你在ax中累积了总和,但是当你退出时你覆盖了ax带有int 21, fn 4c的程序。

巧合的是,这些数字总和为 255,因此它实际上 适合al,这是该中断用于返回代码的寄存器(请参阅 Ralf Brown's excellent interrupt list)。

DOS 是否会用它做任何智能的事情,我不能说:-)

为了在退出程序时保留al,只需这样做:

mov  ah, 0x4c
int  0x21

您可能要考虑做的另一件事是直接打印该项目而不是退回它。以下代码显示了如何使用我的工具库中的一个函数来执行此操作,该函数能够将al 寄存器输出为以十为底的值:

        org     00100h

        mov     bx, num1
        mov     cx, 15
        mov     ax, 0
li:
        add     ax, [bx]
        add     bx, 2
        sub     cx, 1
        jnz     li

        call    prt_byte

        mov     ah, 04ch
        int     021h

num1:   dw      3, 5, 7, 9, 11, 13, 15, 17, 19, 21,23,25,27,29,31
eoln:   db      0dh, 0ah, '$'

prt_byte:
        push    ax
        push    bx
        push    dx

        cmp     ax, 100
        jl      skip_h

        push    ax

        mov     bl, 100             ; divide ax by 100.
        div     bl
        mov     ah, 0

        call    prt_digit

        mul     bl                  ; remove hundreds digit.
        mov     bx, ax
        pop     ax
        sub     ax, bx

skip_h:
        cmp     ax, 10
        jl      skip_t

        push    ax

        mov     bl, 10              ; divide ax by 10.
        div     bl
        mov     ah, 0

        call    prt_digit

        mul     bl                  ; remove tens digit.
        mov     bx, ax
        pop     ax
        sub     ax, bx

skip_t:
        call    prt_digit

        mov     dx, offset eoln
        mov     ah, 9
        int     021h

        pop     dx
        pop     bx
        pop     ax
        ret

prt_digit:
        push    ax                  ; save registers.
        push    dx

        mov     dx, ax              ; put in correct register.
        add     dx, '0'             ; turn into digit.
        mov     ah, 2               ; print.
        int     021h

        pop     dx                  ; restore registers and return.
        pop     ax
        ret

【讨论】:

  • 对于 0-99 整数,div r8 乘以 10 为您提供打印顺序中所需的 2 位数字(商 = al 中的 MSD,它转到内存中的低地址 = 开头如果您存储ax,则为字符串)。因此,您可以添加 0x3030 ('00') 将其转换为两个 ASCII 数字。或者使用 32 位寄存器,add eax, 0x0a3030 将第 3 个字节从 0 转换为换行符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
  • 2018-06-24
  • 1970-01-01
  • 2012-02-26
  • 2016-05-30
  • 1970-01-01
相关资源
最近更新 更多