การพิมพ์ BCD ที่บรรจุ (DT) - ภาษาแอสเซมบลี (TASM)

ฉันพยายามสร้างเครื่องคิดเลขอย่างง่ายในการประกอบ ฉันใช้ TASM (นโยบายของโรงเรียน) ปัญหาคือการพิมพ์ตัวเลขที่บันทึกไว้ด้วยคำสั่ง FBSTP (คำสั่งตัวประมวลผลร่วม) ในตัวแปร DT

FBSTP adr - เก็บที่อยู่ `adr' ซึ่งเป็นค่าที่อยู่ด้านบนของสแต็ก (ST (0)) เป็นเลขทศนิยมแบบแพ็ค (กำหนดที่ "adr" ด้วย DT) ตัวชี้สแต็กจะลดลง การแปลงเสร็จสิ้นในระหว่างกระบวนการจัดเก็บ

ฉันดีบั๊กโปรแกรมแล้วและเมื่อหารด้วย 10 ผลลัพธ์ก็เสียหาย ตัวอย่างเช่น: 12*1=12 ผลลัพธ์ใน res2 ถูกต้อง หลังจากย้ายมันไปที่ AX แล้ว มันยังคงถูกต้อง แต่เมื่อฉันหารมันด้วย 10 DX กลายเป็น 8 แทนที่จะเป็น 2 ดังนั้นแทนที่จะเป็น 12 มันจึงพิมพ์ 18 ฉันยังสังเกตเห็นว่า 12h=18d แต่ฉันไม่สามารถเชื่อมต่อได้ LE: ถ้าฉันใช้ที่เก็บจำนวนเต็มแบบธรรมดาในตัวแปรคำแล้วพิมพ์อันนั้น มันก็ใช้ได้ดี

นี่คือส่วนหนึ่งของโค้ดที่ฉันคิดว่าสำคัญ:

multiplication:
FINIT
FILD x
FILD y
FMUL
FBSTP res2
FWAIT
MOV ax,WORD PTR res2
call write
jmp_line
jmp exit  


write       PROC    NEAR ;my printing proc moves cursor x spaces and starts writing
                          from back to front

    PUSH    DX
            PUSH    AX
    PUSH    CX
    MOV     CX,0

    CMP     AX, 0;check sign
    JNS     ok_write
    NEG     AX ;negate if <0
    MOV     CX,1 ;used to know if number is negative


ok_write:
    printspace ;macro that jumps 5 spaces(maximum number length)
    ;starts printing the number backwards
    print_digit:
    inc len
    ;print each digit
    MOV DX,0 ;prepare DX for storing the remeinder
    DIV CS:ten ;divide AX by 10 so that the last digit of the number is stored
    ADD dl,30h ;transform to ascii
    PUSH AX ;save AX
    MOV ah,02h
    INT 21h  ;print last digit
    printchar   8 ;put cursor over last printed digit
    printchar   8 ;move cursor in front of last printed digit

    cmp divi,1  ;
    JNE not_div
    cmp len,1
    JNE not_div
    printchar '.'
    printchar   8
    printchar   8

    not_div:
    POP AX ;retreive AX
    CMP AX,0 ;when AX=0 the number is written
    JNE print_digit
    ;/print each digit
    CMP     CX,1
    JNE     end_print
    printchar   '-'
   end_print:

    POP     CX
    POP     AX
    POP     DX
    RET
  write       ENDP  

ขอบคุณมาก.


person Vlad Topala    schedule 05.02.2012    source แหล่งที่มา
comment
ฉันไม่ได้วิเคราะห์โค้ดทั้งหมดที่คุณโพสต์ แต่มีสิ่งหนึ่งที่แปลกคือ: DIV CS:ten หาก ten อยู่ในกลุ่มข้อมูลและ CS ไม่เหมือนกับ DS คุณอาจหารด้วยค่าที่แตกต่างจาก ten ลองหารด้วยรีจิสเตอร์ที่โหลดไว้ล่วงหน้าด้วย 10 เช่น mov si, 10+div si.   -  person Alexey Frunze    schedule 30.03.2012


คำตอบ (1)


คุณโหลดหมายเลข BCD ใน AX BCD หมายถึง ทศนิยมที่มีรหัสฐานสอง ดังนั้นแต่ละ 4 บิตจึงเป็นค่าทศนิยม คุณหารด้วย 10 ซึ่งเป็นทศนิยมด้วย แต่ AX ถือว่าตัวเลขเป็นเลขฐานสิบหก หากคุณพยายามหาร 12 (bcd) ด้วย 10 (ทศนิยม) ดังนั้น 12 จะถือเป็นเลขฐานสิบหกและค่าทศนิยมคือ 18 18 หารด้วย 10 (ทศนิยม) หรือ 0Ah จะให้ค่าที่จุดทศนิยม 18 จุดสุดท้าย หาก 12 เป็น bcd คุณจะต้องแปลงจาก bcd ที่แพ็กแล้วเท่านั้น (แต่ละ 4 บิตจะมีรหัสทศนิยมเป็นเลขฐานสิบหก) ไปเป็น unpacked (แต่ละ 8 บิตแทนทศนิยมหนึ่งหลัก) เพื่อให้สิ่งต่าง ๆ ง่ายขึ้น: ถ้า AX มี 12(bcd) คุณสามารถและ AX ที่มี 0Fh เพื่อเอา ​​2 ออกไป และขวานด้วย 0F0h เพื่อเอา ​​1 ออกมา สำหรับตัวเลข คุณเพียงเพิ่ม 30h ("0") ลงไป สำหรับเต็นท์ คุณต้องฉีกขวาน 4 บิตและเพิ่ม 30h ("0") ลงไป อีกครั้ง: หากคุณแปลง bcd ที่บรรจุใน AX = 12 เป็น BCD ที่คลายการแพ็คใน AX = 0102 และเพิ่ม 3030h ลงไป AX จะมี ASCII เป็น 12(bcd) หากต้องการจัดเก็บสิ่งนี้เพื่อพิมพ์บนหน้าจอ คุณต้องทราบว่า 8 บิตล่างจะถูกจัดเก็บไว้ในที่อยู่ที่ต่ำกว่าในหน่วยความจำ ดังนั้นสลับ AH และ AL ด้วย xchg AH, AL ดังนั้น AX = 3231h และจัดเก็บไว้ในตำแหน่งหน่วยความจำใน DS สำหรับตัวเลขที่มากกว่า 99(bcd) คุณควรใช้เทคนิคเดียวกันในการแยกตัวเลขหลักร้อย หลักพัน ฯลฯ... ฉันหวังว่านี่จะทำให้ทุกอย่างกระจ่างขึ้น

person Agguro    schedule 16.02.2015