2012-04-29 2 views
2

숫자를 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 이후에 opcode를 처리하지 않습니다.

* 업데이트되었습니다. 감사합니다 newgre.

+0

어떤 가치가있는 BL합니까? 명시 적으로 지정하지 마십시오. – newgre

+0

네, 죄송합니다. 내가 메인 섹션에서 할당 했어 mov bl, 0x000A; 밑받침 10 전화 format_string; 전화 형식 문자열 프로 시저 –

답변

2

몫 (아래 예제에서 12345 div 10 = 1234 + 나머지 5)이 적합하지 않아서 나눗셈 오버플로 예외가 발생하는 문제가 있습니다. al의 8 비트로 변환합니다 (ah은 나머지가 이미 사용하고 있다는 것을 기억하십시오).

몫 또는 나머지가 대상 레지스터에 맞지 않을 때마다 나눗셈 오버플로 예외가 발생합니다. 0으로 나누는 것만이 원인이 아닙니다.

16/8 = 8 : 8 구분 대신 32/16 = 16 : 16 분할을 수행하려고합니다.

여기 (;;;로 표시) 내 변화에 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 
+0

고마워요 알렉스 = D 그게 분명 도움이되었습니다! 내가 '루프'를 낳은 이유는 아직도 꽤 혼란 스럽다. –

+0

기본 구분 예외 처리기 (BIOS 또는 DOS)가 단순히 IRET을 사용하여 돌아 오는 경우 DIV-> 예외 처리기 -> DIV-> 예외 처리기 -> DIV -> ... 처리기는 이 지침이 어디에 (어떤 프로그램이나 시스템 소프트웨어의 일부로) "알지"못했고 모든 경우에 적절한 조치가 있어야하기 때문에 더 합리적인 조치를 취하지 마십시오. 그것이 할 수있는 최선입니다. 그러나 핸들러를 재정 의하여 프로그램에 적합한 로직을 넣을 수 있습니다. –

+0

핸들러를 재정의하는 방법에 대한 조언이나 참고 자료. 구조체일까요? –