我用汇编编写了一个程序,但输出的开头有一个意外的字符

问题描述 投票:0回答:1

我今天开始学习汇编,我编写了一个程序来打印数字的阶乘。它对于个位数的阶乘非常有效,但是当我对其进行一些更改以处理更大的数字时,我开始在阶乘的开头出现一个意想不到的字符。阶乘开头的字符对于每个数字都会发生变化。

这是我的代码:

section .data
    msg db 'Enter a number: ',0                                   ;content of user prompt
    lenmsg equ $ - msg                                                  ;length of user prompt
    disp db 'Factorial: ',0                                             ;content of output
    lendisp equ $ - disp                                                ;length of output
    newline db 0xa                                                      ;newline char

section .bss
    num resb 3                                                          ;2 bytes for number , 1 byte for newline
    fac resb 12                                                         ;12 bytes for Factorial

section .text
    global _start

_start:

    ;Display User Prompt
    mov edx,lenmsg                                                      ;number of bytes to write
    mov ecx,msg                                                         ;content to write
    mov ebx,1                                                           ;file descriptor : stdout
    mov eax,4                                                           ;system call : sys_write
    int 0x80                                                            ;call kernel

    ;Accept User Input
    mov edx,2                                                           ;number of bytes to read
    mov ecx,num                                                         ;input stored at num
    mov ebx,0                                                           ;file descriptor : stdin
    mov eax,3                                                           ;system call : sys_read
    int 0x80                                                            ;call kernel
    mov byte [num+eax-1],0                                              ;replace newline with null
    
    ;Calculate Factorial
    movzx eax, byte [num]                                               ;move num to eax, replace leading places with zeroes
    sub eax,'0'                                                         ;convert ascii to integer
    mov ecx,eax                                                         ;transfer to ecx , acts as counter
    mov eax,1                                                           ;eax takes value of 1, acts as factorial
    cmp ecx,0                                                           ;checks if input is 0
    jz output                                                           ;if input is 0 it goes directly to output
    loop:
        mul ecx                                                         ;multiply
        dec ecx                                                         ;decrease counter
        jnz loop                                                        ;if ecx > 0, loop through

output:

    ;Convert integer to ASCII
    mov ebx,fac+11                                                      ;fac is 12 bytes long, fac+11 goes to end of fac
    mov byte [ebx],0                                                    ;add null character
    xor ecx,ecx                                                         ;clear ecx , acts as counter
    convert:
        xor edx,edx                                                     ;clear edx
        mov ecx,10                                                      ;divisor
        div ecx                                                         ;eax /= ecx, edx contains remainder
        add dl,'0'                                                      ;last 8 bits of edx contains the digit, convert it into a string by adding ascii number of '0'
        dec ebx                                                         ;move buffer pointer, we save each digit in a different position
        mov [ebx],dl                                                    ;store character
        inc ecx                                                         ;ecx works as a general purpose register AND as a counter at the SAME TIME
        test eax,eax                                                    ;works like bitwise AND
        mov [fac],bl                                                    ;store result to fac
        jnz convert                                                     ;if eax != 0, continue looping


    ;Display Output Message
    mov edx,lendisp                                                     ;length of output message
    mov ecx,disp                                                        ;content of output message
    mov ebx,1                                                           ;file descriptor : stdout
    mov eax,4                                                           ;system call : sys_write
    int 0x80                                                            ;call kernel

    ;Display Factorial
    mov edx,ecx                                                         ;length of factorial
    mov ecx,fac                                                         ;content of factorial
    mov ebx,1                                                           ;file descriptor : stdout
    mov eax,4                                                           ;system call : sys_write
    int 0x80                                                            ;call kernel

    ;Display Newline
    mov edx,1                                                           ;length of newline
    mov ecx,newline                                                     ;content of newline
    mov ebx,1                                                           ;file descriptor : stdout
    mov eax,4                                                           ;system call : sys_write
    int 0x80                                                            ;call kernel

    ;Exit Code
    mov eax,1                                                           ;system call : sys_exit
    int 0x80                                                            ;call kernel

这是我得到的输出:

输入数字:2
阶乘:-2

输入数字:3
阶乘:-6

输入数字:4
阶乘: ,24

输入数字:5
阶乘:+120

输入数字:6
阶乘:+720

输入数字:7
阶乘:*5040

输入数字:8
阶乘:)40320

输入数字:9
阶乘:(362880

我在 Ubuntu 24.04.1 LTS 上使用 NASM 版本 2.16.01。

请帮助我。

assembly x86 output nasm factorial
1个回答
1
投票

当您准备好显示阶乘时,当前首先会显示一条消息。这破坏了您认为在转换循环期间在 ECX 中建立的计数。 转换循环还有
一些无意义的内容

这就是您所需要的:

;Display Output Message mov edx, lendisp mov ecx, disp mov ebx, 1 mov eax, 4 int 0x80 ;Convert integer to ASCII mov ecx, fac+12 ; Better build address in ECX, ready for output xor ebx, ebx ; Count in any temp register mov edi, 10 ; CONST throughout the loop convert: xor edx, edx div edi add dl,'0' dec ecx mov [ecx], dl inc ebx test eax, eax jnz convert ;Display Factorial mov edx, ebx mov ebx, 1 mov eax, 4 int 0x80
看到,通过将消息

放在转换之前,您可以更自由地使用寄存器。


你的阶乘循环不应该乘以 1

既然都是0!和 1!为 1,立即将两者分开。 然后提前停止循环:

mov eax, 1 cmp ecx, eax jbe output loop: imul eax, ecx ; Non-widening is better (you don't use EDX) dec ecx cmp ecx, 1 jne loop output:
    
© www.soinside.com 2019 - 2024. All rights reserved.