【问题标题】:How to find the factorial of 5 using NASM?如何使用 NASM 找到 5 的阶乘?
【发布时间】:2021-09-11 07:16:01
【问题描述】:

我刚刚开始使用 tutorialspoint 的在线 Asm 编译器 (https://www.tutorialspoint.com/compile_assembly_online.php) 学习 NASM。

我的第一个热身是编写一个计算 5 阶乘的代码。这是我的尝试:

section .text
    global _start      
_start:     
    mov eax, 1      ;a = 1
    mov ebx, 1      ;f = 1
    int 0x80        ;call kernel
    
l1:
    mul ebx        ; f = f*a
    inc eax        ; a++
    cmp eax, 5     ; if a<=5
    jle l1         ; jump to l1

section .data
msg db 'Factorial 5 is:',0xa    
len equ $ - msg 

它没有打印出任何值,谁能给我提示一下问题出在哪里?谢谢。

【问题讨论】:

  • 你知道 EAX=1 是 SYS_exit,对吧?所以int 0x80 只是退出你的程序。使用调试器单步执行您的代码。当然,如果您不进行任何 write 系统调用或调用 printf 或其他任何东西,它也不会打印任何内容。
  • 由于那个在线IDE好像没有调试器,所以学习asm没用。不得不向 Stack Overflow 询问有关使用调试器单步执行时完全显而易见的事情的问题是浪费您自己的时间(以及其他所有人的时间)。 IIRC,onlinegdb.com 有一个 asm 模式,但我忘记了它是否有 NASM 或只是 GAS,如果它支持 32 位模式而不是本机 64 位 x86-64,我忘记了 IDK。 Linux 是免费的,NASM + 文本模式 GDB 非常轻量级;本地安装应该很有意义。
  • 可以mov eax,5*4*3*2 - 可能会更快。
  • mul ebx ; f = f*a 是错误的,如果你考虑ebx 中的feax 中的a。它实际上做的是a = f * a。 (当然还要将上半部分写成edx。)如果你想乘以ebx,请使用imul ebx, eax

标签: assembly x86 nasm factorial


【解决方案1】:

我不会使用 mul 操作。在汇编中,你要坚持简单,避免除法、乘法和浮点,除非你别无选择。

5! = 5 * 4 * 3 * 2 = 5 * 3 * 2 * 2 * 2 = (5 * 2 + 5 ) * 2 * 2 * 2

所以,计算这个:

5 << 1
ADD 5
<< 3

不需要循环或乘法。如果您要使用循环(或者如果这是课程的重点),通常在汇编中您会比较零,所以您倒数,而不是倒数。

在汇编中使用调试器是必不可少的。您的代码存在一些结构性问题,使用调试器单步执行会发现这些问题。您不能只使用在线系统。您必须在计算机上设置调试器。

【讨论】:

  • &gt;&gt; 是右移,看起来你的意思是左移。 (或lea ebx, [ebx + ebx*2],因为这是一个 x86 问题)
  • @PeterCordes 哎呀,正在修复它。
  • 当然,如果您要对一个小阶乘进行特殊处理,而不是通过练习来学习编写循环,那么在运行时进行任何计算都是毫无意义的。 mov eax, 5 * 4 * 3 * 2 * 1 组装成 mov eax,0x78。或者您甚至可以使用%rep%assign 进行汇编时阶乘“循环”,更新一个NASM 预处理器变量,然后您将其用作mov eax, fact
  • 当然,即使在运行时对于一般情况,您也不需要mul,您需要更快的imul ebx, eax(问题中的代码似乎认为 mul会做,基于它递增 eax...)
  • 顺便说一句,整数乘法在现代 x86 上并不慢。 Zen 和 Intel 几代以来,以 3 个周期延迟(和 1/时钟吞吐量)运行它,与 Intel 上 tzcnt 上的 popcnt 相同。整数除法仍然很慢,并且没有完全流水线化,因此将 imul 与 div/idiv 混为一谈并不明智。此外,如果您仔细使用浮点数,它并不慢。除除法之外的 FP 操作的 4 个周期延迟和 2 个时钟吞吐量非常适合数字运算。在整数和 FP 之间来回获取数据需要花费指令,当然应该避免。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多