assembly - 8086组装师

标签 assembly nasm x86-16

我在下面的代码中遇到了这个问题,该代码将数字转换为 ASCII“数字文本”。然而,代码似乎在“div”操作码处循环

;Main Program
main:
    mov ax, 0x0000
    mov ds, ax ; setup data segment register
    mov si, GreetString ; setup data segment offset
    call print_string ; call print string procedure
    mov si, DataWord ; setup data segment offset
    mov bl, 0x000A ; base 10
    call format_string ; call format string procedure
    mov si, GreetString ; setup data segment offset
    call print_string ; call print string procedure
prevent_overflow:
    hlt ; halt the CPU
    jmp prevent_overflow

format_string:
mov ax, [ds:si] ; load register ax with data
xor cx, cx ; set counter to 0
mov si, GreetString ; set pointer to address of GreetString

.format_char:
div bl ; divides by register bl
add ah, 48 ; convert to ascii numeric
mov [ds:si], ah ; move ascii numeric to ds:si
inc cx ; increase counter
inc si ; increase si
xor ah, ah ; clear ah register
or ax, ax
jnz .format_char ; jump to format next char
ret

知道为什么会发生这种情况吗?我说“循环”是因为我的 CPU 处于最大值并且不会继续处理 div 之后的操作码

*已更新。谢谢纽格雷。添加了主要部分以使其更具可读性 (^.^)

最佳答案

问题是您会遇到除法溢出异常,因为商(在下面的示例中为 12345 div 10 = 1234 + 5 的余数)不适合 al 的 8 位(还记得 ah 已经被其余部分使用了吗?)。

每次商或余数不适合目标寄存器时,都会出现除法溢出异常。不仅仅是除以 0 造成的。

您想要进行 32/16=16:16 除法,而不是 16/8=8:8 除法。

以下是我所做的更改在 DOS 中的效果(标记为 ;;;):

; file: div2.asm
; compile as: nasm -f bin div2.asm -o div2.com
org 0x100 ;;;

;Main Program
main:
    mov ax, 0x0000
;    mov ds, ax ; setup data segment register ;;;
    mov si, GreetString ; setup data segment offset
    call print_string ; call print string procedure
    mov si, DataWord ; setup data segment offset
    mov bl, 0x000A ; base 10
    call format_string ; call format string procedure
    mov si, GreetString ; setup data segment offset
    call print_string ; call print string procedure

    ret ;;;

prevent_overflow:
    hlt ; halt the CPU
    jmp prevent_overflow

format_string:
mov ax, [ds:si] ; load register ax with data
xor cx, cx ; set counter to 0
mov si, GreetString ; set pointer to address of GreetString

.format_char:
; div bl ; divides by register bl ;;;
xor dx, dx ;;;
xor bh, bh ;;;
div bx ;;;

; add ah, 48 ; convert to ascii numeric ;;;
add dl, 48 ;;;

; mov [ds:si], ah ; move ascii numeric to ds:si ;;;
mov [ds:si], dl ; move ascii numeric to ds:si

inc cx ; increase counter
inc si ; increase si
; xor ah, ah ; clear ah register ;;;
or ax, ax
jnz .format_char ; jump to format next char

mov byte [ds:si], "$" ;;;
inc cx ; increase counter ;;;
inc si ; increase si ;;;

ret

print_string: ;;;
    pusha ;;;
    mov ah, 9 ;;;
    mov dx, si ;;;
    int 21h ;;;
    popa ;;;
    ret ;;;

DataWord dw 12345 ;;;
GreetString db "Hello World!", 13, 10, "$" ;;;

它打印:

Hello World!
54321

关于assembly - 8086组装师,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10371353/

相关文章:

java - 使用 Java 和汇编语言构建一个在 "bare metal"上运行的系统

c - 了解 Aleph One 的第一个缓冲区溢出漏洞

assembly - 0和双字0有什么区别?

arrays - 访问 emu8086 中的数组

组装:打印时无意中添加十六进制数字

c# - C# 64 位发布代码的反汇编 View 比 32 位调试代码长 75%?

c++ - 在 C/C++ 中数组是否以相反的顺序存储?

汇编,将单个字节从寄存器写入内存会覆盖其他字节

macos - 如何在asm中使用malloc

assembly - 在程序集中添加有符号数字