assembly - 使用 NASM 程序集将 16 位十进制数转换为其他基数

标签 assembly nasm

我在使用 NASM 程序集实现正确的十进制到二进制、八进制和十六进制转换时遇到了一些问题。我有大部分代码如下,我知道有一些问题我仍在努力解决。我已经在代码中注释了相关信息。

    %include "io.mac"
    .STACK 100H
    .DATA
    msg1        db "Please enter a positive integer (max 16 bits): ",0
    msg2        db "The binary (base-2) representation of the number is: ",0
    msg3        db "The octal (base-8) representation of the number is: ",0
    msg4        db "The hex (base-16) representation of the number is: ",0
    msg5        db "A",0 ;These will be implemented when I get the 
    msg6        db "B",0 ;hexadecimal loop working to change 10, 11, 
    msg7        db "C",0 ;etc. to their hex equivalents.
    msg8        db "D",0
    msg9        db "E",0
    msg10       db "F",0

    .UDATA
    num1            resw 1
    quotient        resw 1
    remainder       resw 1

    .CODE
    .STARTUP
    PutStr msg1
    nwln
    GetInt [num1]

    nwln
    PutStr msg2
    nwln
    mov AX, [num1]      
    sub BH, BH

    binary_loop:
    push AX 
    mov BH, byte 2 
    div BH ;All loops output the remainders in reverse order at the moment.
    mov [remainder], AH ;I was thinking of maybe moving the remainder value
    PutInt [remainder] ;to a stack then calling it at the end of the loop,
    mov [quotient], AL ;when the quotient value is zero. However,  
    mov AX, [quotient] ;I do not know enough to make that work. Any help
    cmp [quotient], byte 0 ;would be greatly appreciated
    jz binary_done ;Could also be je, as both do the same thing
    loop binary_loop

    binary_done:
    nwln
    PutStr msg3
    nwln
    mov AX, [num1]
    sub BH, BH      

    octal_loop:     
    push AX
    mov BH, byte 8
    div BH
    mov [remainder], AH
    PutInt [remainder]
    mov [quotient], AL
    mov AX, [quotient]
    cmp [quotient], byte 0
    jz octal_done
    loop octal_loop

    octal_done:
    nwln
    PutStr msg4
    nwln
    mov AX, [num1]      
    sub BH, BH  

    hex_loop:
    push AX
    mov BH, byte 16
    div BH
    mov [remainder], AH
    PutInt [remainder]
    mov [quotient], AL
    mov AX, [quotient]
    cmp [quotient], byte 0
    jz done
    loop hex_loop

    done:
    .EXIT

测试 16 位数字 155 的当前输出: 二进制:11011001 八进制:332 十六进制:119

最佳答案

您的代码有 3 个主要问题:

  • 它以相反的顺序显示数字
  • 它将十六进制数字显示为整数(例如 0xB 显示为 11)
  • 它的评论非常糟糕(汇编不是高级语言)

您的代码还有其他问题:

  • 没有有效地使用寄存器(而是将内容存储在较慢的变量中)
  • 代码重复——接受“base”作为输入的单个例程将使代码大小减半
  • 滥用宏(“语言中的语言”);这使得代码更难理解(例如,我无法判断 PutInt 是函数调用还是内联代码,或者它使用了哪些寄存器/垃圾)并且无法优化周围的指令正确

对于第一个问题,最好的办法是在内存中倒序构建一个字符串,然后打印得到的字符串。对于第二个问题,您需要停止使用 PutInt - 每个数字都应转换为一个字符。

例如(32 位 80x86,NASM,未测试):

;Convert unsigned integer to string
;
;Input
; eax = integer
; ebx = base
;
;Output
; edi = address of string
;
;Trashed
; eax,edx

    section .bss
tempString: resb 33              ;Worst case string size is 32 digits
                                 ; (for base2), plus string terminator
tempStringEnd:
    section .text

convertIntegerToString:
    mov byte [tempStringEnd-1],0 ;Store string terminator
    mov edi,tempStringEnd-2      ;edi = address to store last character

.nextDigit:
    xor edx,edx                  ;edx:eax = current value
    div ebx                      ;eax = new current value, edx = next digit
    add dl,'0'                   ;dl = character for next digit maybe
    cmp dl,'9'                   ;Is the character correct?
    jbe .gotChar                 ; yes
    add dl,'A'-'0'-10            ; no, fix it up
.gotChar:
    mov [edi],dl                 ;Store the character
    dec edi                      ;edi = address for next character
    test eax,eax                 ;Is the current value zero?
    jne .nextDigit               ; no, do the next digit

    ret                          ;Done, EDI = address of completed string

关于assembly - 使用 NASM 程序集将 16 位十进制数转换为其他基数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29885580/

相关文章:

string - 无法理解寄存器和变量之间的汇编mov指令

linux - Kdbg 中显示的值是错误的 -- NASM

linux - 为什么 seccomp 禁止我正常的系统调用

c - 从 C 调用获取 ASM 中的参数

c - NASM 汇编数理逻辑

linux - 组装 - NASM 析因问题

gcc - GCC 上 x86 intel asm 方括号前的偏移量

gcc - Gdb 在调试 ARM7 微 Controller 的汇编程序时跳过源代码行

winapi - 汇编器 : Getting Win32's WinMain on-stack parameters

c - IA32 寄存器地址