【问题标题】:NASM program Assembly Language [closed]NASM程序汇编语言[关闭]
【发布时间】:2014-12-26 17:36:59
【问题描述】:

程序:输入一个从 0 到 255 的以 10 为底的整数,并将该数字更改为以 n 为底的数字(其中 n 是从 2 到 9)。

我知道如何将基数从 10 转换为 2。但不知道如何将基数 10 转换为任何其他基数。 任何链接或示例都足以让我开始。

【问题讨论】:

  • 这是初等数学。在循环中除以基数,并反向记下余数。

标签: assembly nasm


【解决方案1】:

为了提供原始答案的翻译,并注意给一个人一条鱼并喂他一天,以下是NASM的翻译。 注意:这是原始代码中的 32 位代码:

; build and link (32-bit on x86_64)
;
; nasm -f elf -o baseconvert_32.o baseconvert_32.asm
; ld -m elf_i386 -o baseconvert_32 baseconvert_32.o

section .data

    base10  db 255
    newbase db 7
    result times 8 db 0
    newline db 10

section .text
                global _start

        _start:
                mov     edi, result         ; offset in result string

                xor     ax, ax              ; zero/clear ax register
                mov     al, [base10]        ; at start, current remainder = whole value
                mov     bl, [newbase]

        loop:
                div     bl                  ; divide current remainder by new base
                mov     [edi], ah
                cmp     al, 0               ; is the quotient zero?
                je      printchar           ; if it is we are done
                xor     ah, ah
                inc     edi                 ; move offset in result string (note digits
                jmp     loop                ; of answer are stored in reverse order)

        printchar:
                add    byte [edi], 48       ; add ascii '0' to digit to get printable char
                mov     eax, 4              ; linux sys_write
                mov     ebx, 1              ; stdout
                mov     ecx, edi            ; point to current digit
                mov     edx, 1              ; number of chars to print
                int     0x80                ; syscall
                dec     edi                 ; point to next digit
                cmp     edi, result         ; are we past the final digit?
                jge     printchar           ; if not, keep printing to stdout

                ; print newline
                mov     eax, 4
                mov     ebx, 1
                mov     ecx, newline
                mov     edx, 1
                int     0x80

                xor     ebx, ebx            ; set zero exit code
                mov     eax, 1              ; set syscall number to __NR_exit 1 (0x1 hex)
                int     0x80                ; call kernel (syscall 32-bit)

输出:

$ ./baseconvert_32
513

【讨论】:

    【解决方案2】:

    嗯,它不是 NASM,它是 gas,但下面的代码在 Linux 上对我有用。也许你或一些友好的*er可以translate it into NASM

    使用gcc -nostdlib -g -o filename filename.s在linux上编译。

    您可以将 255 和 7 更改为您想要的除数和基数。

    如果您没有运行 Linux/Unix,则系统调用不太可能起作用。

    algorithm 相当简单。

    .data
    
    base10:
        .byte 255
    newbase:
        .byte 7
    result:
        .byte 0,0,0,0,0,0,0,0 # since dividend <=255 and divisor >=2
                              # 8 digits in the new base is enough
    newline:
        .byte 10 
    
    .text
    
    .global _start
    _start:
    
        movl $result, %edi  # offset in result string
    
        xorw %ax, %ax
        movb base10, %al    # at start, current remainder = whole value
        movb newbase, %bl   
    
    loop:
        divb %bl            # divide current remainder by new base
        movb %ah, (%edi)
        cmpb $0, %al        # is the quotient zero?
        je printchar        # if it is we are done
        xorb %ah, %ah
        incl %edi           # move offset in result string (note 
        jmp loop            # digits of answer are stored in reverse
                            # order)
    
    printchar:
    
        addl $48, (%edi)    # add ascii '0' to digit to get printable char
        movl $4, %eax       # linux sys_write
        movl $1, %ebx       # stdout
        movl %edi, %ecx     # point to current digit
        movl $1, %edx       # one char to print
        int $0x80           # syscall
        decl %edi           # point to next digit
        cmpl $result, %edi  # are we past the final digit?
        jge printchar       # if we aren't keep going
    
        # print a newline
        movl $4, %eax       
        movl $1, %ebx
        movl $newline, %ecx
        movl $1, %edx
        int $0x80
    
        # finish nicely
        movl $0, %ebx   
        movl $1, %eax
        int $0x80
    

    【讨论】:

    • 是的,给 OP 完整的工作代码会教他任何东西。
    • @JonathonReinhart:SO 是一个教育网站吗?