Ch 25 FPU (4) IEEE 與 BCD

這一章小木偶將介紹兩個有用的副程式,一個是可以把 FPU 的堆疊頂直接印在螢幕上 (註一),另一個是可以接受 ASCII 阿拉伯數字字串並存入 FPU 堆疊頂。

為了了解把堆疊頂數值印在螢幕上,必須先說明什麼是『科學記號』?『科學記號』是一種可以表示很大或很小數的一種表示方法,任何數均可以化成

a×10x

這個記號,a×10x,就稱為『科學記號』,其中 a 必須在 1 和 10 之間,可以等於 1 但不能等於 10,而 x 是整數,可以是正數、負數或零。至於 a 與 x 中文如何稱呼?小木偶不知道,但下文要用到,姑且稱它們為『有效數』與『次方數』。例如:

       1 = 1×100
54000000 = 5.4×107
0.000022 = 2.2×10-5

第三個例子,2.2 稱為『有效數』,-5 稱為『次方數』。『科學記號』用來表示很大或很小的數時,很方便而且一目了然,所以小木偶前面所提到的兩個副程式就是把 FPU 堆疊頂以科學記號表示,另一個副程式是輸入科學記號字串,轉換成 IEEE 格式存於堆疊頂。而實際輸入時 10 的次方數用『E』表示,例如 2.3E2 即 2.3×102


IEEE 轉換成 ASCII 字串:ieee_to_ascii_5c

原理

要把 FPU 堆疊頂以 ASCII 文字字串的科學記號表示出來,必須求出『有效數』和『次方數』。在 FPU 指令中有一個 FBSTP 指令可以把 IEEE 格式的整數轉換成聚集 BCD 數,本程式就是想辦法把『有效數』轉換成整數,而次方數必定是整數,再用 FBSTP 指令存成聚集 BCD 數,再調整有效數的小數點位置就成了。

次方數的求法並不難,利用以 10 為底的對數很容易就算出來了。

log10(a×10x) = log10a + log1010x = log10a + x

其整數部份就是次方數,但是 x87 指令堥癡S有求以 10 為底的對數值,只有求以 2 為底的對數值,即 FYL2X,不過還好小木偶還記得國中老師教的,用『換底公式』可以計算出來,換底公式是:

換底公式

換句話說,只要先使 ST(1) 與 ST 之值分別是 1 與要在螢幕上顯示的數,再用 FYL2X 指令把 ST 變成以 2 為底的對數值,再除以 Log210 ,最後再把結果自整數捨去就可得到次方數。求出次方數後再求有效數就不難了。其實您可以想像,有效數就是原來的值 (要顯示在螢光幕的數) 除以 10 的次方數。小木偶想舉個例子說明,可能會更清楚一些。

假如有一個數 57923.8912 要把它變成科學記號,顯然答案是 5.79238912×104,在小木偶的程式堿O先計算 log1057923.8912,這個對數值是 4.762857729,只要取整數部份即為次方數。把原來的數除以 104 就得到有效數 5.79238912 了。只不過這樣算出來的有效數仍是經過編碼的 IEEE 格式,但是如果乘以 1017,就可以變成整數,再用 FBSTP 這個指令直接把它以 packed BCD 的格式存入記憶體中,這樣就很容易變成用 ASCII 格式了。

為何要乘以 1017 呢?原來是以 FBSTP 存入的整數最大有 18 位,而扣掉個位數,所以乘以 1017 就足以應付了。

原始碼

和前一章一樣,要組譯成 COM 檔的程式碼和 EXE 不同。而組譯給 EXE 用的副程式稱為 ieee_to_ascii_5x,只能被 EXE 檔呼叫,組譯給 COM 檔用的程式稱為 ieee_to_ascii_5c,能被 EXE 檔或 COM 檔呼叫。此處的 5 是指給 Pentium 等級或及其以上的 CPU 使用的副程式。底下是 ieee_to_ascii_5c 的原始碼:

        .286
        .8087
;***************************************
code    segment byte
        assume  cs:code,ds:code
        public  ieee_to_ascii_5c
        extrn   x_p_y_5c:near
;---------------------------------------
;目的:此副程式是將 8087 ST 暫存器內之實數,轉換成
;      ASCII 數字字串之格式,並存於DS:BX所指定的位址
;      建檔於1990.05.15 20:21 修改於 1998.03.25 am
;輸入:ST - 欲轉換之實數
;      DS:BX - 字串儲存位址,必需有 26 bytes,大位數於低位址
;輸出:ST - 欲轉換之實數
;      DS:BX - ASCII 格式的數字字串,大位數於低位址
ieee_to_ascii_5c        proc    near
        push    si
        call    realad
addrad  equ     this word
realad: pop     si
        sub     si,offset addrad
        ftst                    ;022 因 Log2 0 會造成無意義,故先測試是否為0
        push    ax
        fstsw   cs:sw[si]
        fwait
        mov     ax,cs:sw[si]    ;--st0--;--st1--;--st2--;026
        sahf                
        fld     st              ;   x   ;   x   ;       ;028 假設要印出的數為 x
        jne     non_z
;030 ST為0時,exp和mans均為0
        fbstp   cs:exp[si]      ;   x   ;
        fld     st              ;   x   ;   x   ;
        jmp     short ok_z
;034 ST 不為零時,先計算出指數為何
non_z:  fabs                    ;  |x|  ;   x   ;
        fld1                    ;   1   ;  |x|  ;   x   ;039
        fxch    st(1)           ;  |x|  ;   1   ;   x   ;037
        fyl2x                   ;log2|x|;   x   ;
        fldl2t                  ;log2 10;log2|x|;   x   ;039
        fdivp   st(1),st        ;e=log x;   x   ;        040 指數為『e的整數部份』
        fstcw  cs:cw[si]                ;041 保存現有捨入方法
        fwait
        push    cs:cw[si]
        and     cs:cw[si],not 0c00h     ;044 更改捨入方法為『向負無窮大』捨入
        or      cs:cw[si],0400h
        fldcw   cs:cw[si]               ;046 載入新的捨入方法
        frndint                 ;i=int e;   x   ;       ;047 把 e 捨入成 i
        pop     cs:cw[si]                               ;    i 即為指數部份
        fldcw   cs:cw[si]                               ;049 存回舊的捨入方法
        fld     st              ;   i   ;   i   ;   x
        fbstp   cs:exp[si]      ;   i   ;   x   ;       ;051 把 i 存入 exp 變數
        fchs                    ;  -i   ;   x   ;
        fild    cs:ten[si]      ;   10  ;  -i   ;   x   ;053 載入 10
        call    x_p_y_5c        ;  10-i ;   x   ;
        fmul    st,st(1)        ; x/10i ;   x   ;
        fmul    cs:ten17[si]    ;  sig  ;   x   ;       ;056 sig 為『有效數』
ok_z:   fbstp   cs:mans[si]     ;   x   ;

;059 將mans,exp之packed BCD轉換成ASCII數字字串
        cld
        push    di              ;061 存入原暫存器
        push    bx
        push    es
        mov     di,bx           ;065 DI=IEEE數轉換成ASCII後的存放位址
        push    ds
        pop     es              ;066 使 ES=DS
        mov     bx,offset mans+9
        add     bx,si           ;068 BX=『有效數』最高位址
        mov     al,cs:[bx]      ;069 AL=『有效數』的正負號
        call    set_sign
        dec     bx              ;071 BX=『有效數』的次高位址,此位址為數值開始
        mov     al,cs:[bx]      ;072 AL=『有效數』的第一位與第二位
        mov     ah,al
        and     al,0f0h         ;074 先處理 AL 的較大位數
        shr     al,4
        call    set_nibble
        mov     al,'.'          ;077 存入小數點
        stosb
        mov     al,ah           ;079 再處理 AL 的較小位數
        call    set_nibble
        push    cx
        dec     bx              ;082 再處理其他 16 位數
        mov     cx,8
agin0:  call    set_byte
        loop    agin0
        mov     al,'E'          ;086 存入『E』
        stosb
        mov     bx,offset exp+9
        add     bx,si           ;089 BX=指數最高位址
        mov     al,cs:[bx]      ;090 AL=指數的符號
        call    set_sign
        mov     cx,2            ;092 指數最多位數為四位數
        sub     bx,8            ;093 BX=跳過零後的指數最高位址
agin1:  call    set_byte
        loop    agin1
        pop     cx
        pop     es
        pop     bx
        pop     di
        pop     ax
        pop     si
        ret

;104 設定正負號
set_sign:       or      al,al
                mov     al,'+'
                jz      positive
                mov     al,'-'
positive:       stosb
                ret

;112 解開 AL 的 packed BCD 數,並存入 DI 所指的位址 
set_byte:       mov     al,cs:[bx]
                mov     ah,al
                shr     al,4
                call    set_nibble
                mov     al,ah
                call    set_nibble
                dec     bx
                ret
                
set_nibble:     and     al,0fh
                add     al,'0'
                stosb
                ret

;127 資料區
mans    dt      0
exp     dt      0
ten17   dq      1.0E17
ten     dw      10
cw      dw      ?       ;控制字組
sw      dw      ?       ;狀態字組
ieee_to_ascii_5c        endp
;---------------------------------------
code    ends
;***************************************
        end     ieee_to_ascii_5c

這個程式可以把它存成 IEEE2A5C.ASM 然後組譯並加入程式庫,MYASMLIB.LIB。


新的指令

.286

這個指令是表示可以使用 80286 新增的指令集。在這個程式堬 75 行出現『shr al,4』這一條指令只能在 80286 及其以上等級的 CPU 使用,如果是在 8087 使用必須改成

mov     cl,4
shr     al.cl

NOT

這是一個邏輯運算指令,它的意思是『非』運算,意思是把 0 變成 1,1 變成零,在組譯時,MASM 就會自動算出真實數值是多少,而寫入目的檔。例如本程式的第 44 行,not 0c00h,小木偶為說明方便先把 0c00h 換成二進位是 0000 1100 0000 0000,not 運算是把 0 變成 1,1 變成零,所以 not 0c00h 就變成 1111 0011 1111 1111,即 0f3ffh。( 其實 not 0c00h= 0f3ffh )

FSTCW/FLDCW 儲存/載入控制字組

先說說 FSTCW 指令,這個指令是把 FPU 上的『控制字組』的內容儲存到一個 16 位元的記憶體變數中,有關控制字組的詳細說明請參閱附錄二控制字組

FLDCW 是把一個 16 位元記憶體變數載入到 FPU 的控制字組中。這個 16 位元記憶體變數之數值將會改變 FPU 的例外條件的處理、如何捨入、控制實數精確度等等操作。


ieee_to_ascii_5c 關鍵過程說明

小木偶將說明這個程式的幾個關鍵過程:求次方數的捨去、求有效數。

求次方數的捨去

在本程式中,要求某數的變成科學記號時,10 的次方數是多少?最簡單的方法是取其常用對數值。舉例來說:1234=1.234×103次方數是 3,而 Log 1234=3.091315,取其整數部份就是10 的次方數了。再看另一個例子,0.00222=2.22×10-3,次方數是 -3,而 Log 0.00222=-2.653647,如果只取整數部份,顯然是不對的,但是如果『向負無窮大捨去』結果就成為 -3,也就是十的次方數了。而前一個例子,向負無窮大捨去也得到正確的結果,所以本程式中捨去方式是『向負無窮大捨去』。

要使 FPU 向負無窮大捨去,必須改變控制字組。第 41 行先由 FSTCW 取得控制字組之資料存於 cw 變數中,這是因為我們沒有變法對控制字組直接運算。再查附錄二控制字組得知,要使 FPU 向負無窮大捨去應使第 10、11 位元分別為 0、1,所以在第 44 行先使 cw 的第 10、11 位元均別為 0 ( 對原控制字組之資料做 and 0f3ffh 運算 ),再使第 10 位元變為 1 ( 對控制字組之資料做 or 400h 運算 )。最後再用 FLDCW 指令使新的 cw 載入到 FPU 堛滷惆謢r組,這樣 FPU 做捨去動作時就會向負無窮大捨去了。

求有效數

小木偶想還是舉例說明好了。例如 1234.567=1.234567×103,有效數是 1.234,雖然 FBSTP 可以把 IEEE 但是前提必須是使堆疊頂為整數,否則會自小數點以下捨去。如何使其為整數呢?當然就是乘以 10、100、1000、10000……,但是要乘以那一個得看小數位數而定,這樣很麻煩,小木偶有個間接的方法,就是先除以該數的 10 的次方數,再乘以 1017,為何乘以 1017 呢?原因是 FBSTP 可以有 18 位數。例如這個例子,1234.567 先除以 1000,變成 1.234567,再乘以 1017 變成 123456700000000000,這是一個很大的整數,把它用 FBSTP 指令以聚集 BCD 數存入 mans 變數中,而小數點的位置在第一位數字之後。

FBSTP 存入時,必須先設一個 10 位元組的記憶體變數,也就是 mans,最高位址的那一個位元組只有第 7 位元是表示符號,其他第 0 到第 6 位元都沒有使用。而後共有九個位元組,可以表示 18 位的聚集 BCD 數。原始程式的第 59 行到第 125 行就是根據上述編碼方式,解開這個聚集的 BCD 數的程式。


ASCII 字串轉換 IEEE:ascii_to_ieee_5c

這個副程式是用來把一個字串變成 IEEE 實數格式,並存於 ST 暫存器中。而這個字串可以是 ASCII 編碼的阿拉伯數字,或是非聚集的 BCD 數字,但是都必須以歸位字元 (0DH) 做為結尾,且大位數在低位址。

小木偶為什麼要寫這個程式呢?原來當使用者以鍵盤輸入數字時,其實每按下一個鍵,電腦將其掃描碼與 ASCII 碼記錄於記憶體中成為字串,但這些字串無法為 FPU 立即運算,即使是 CPU 也只能做聚集或非聚集的 BCD 運算,所以小木偶依照 AH=0AH/INT 21H 所輸入字串格式,寫了這個副程式,把字串化成實數。

這個副程式所能接受的字串包含 ASCII 字串與非聚集的 BCD 數,換句話說 ASCII 字元只要在 30H 到 39H 或是數字在 00H 到 09H 都可以,此外字串包含小數點『.』(2EH) 或是『E』、『e』也可以被接受的。『E』、『e』是表示十的幾次方的意思。

原始程式

cr      equ     0dh
;***************************************
code    segment byte
        assume  cs:code,ds:code
;---------------------------------------
;目的:將 ASCII 數字格式轉換成 IEEE 實數格式並存於 ST 堆疊暫存器
;日期:建立於1990.12.01 1:19,修改於1998.04.07,2003.01.01
;輸入:DS:BX - ASCII 數字字串或非聚集 BCD 數起始位址,此數字字串的較大數在低位址,
;              且以 0dh 字串結束符號,例如:01 02 03 2E 04 45 02 0D 表示 123.4E2
;              或 31 32 33 2E 34 65 32 0D 表示 123.4E2,都是可以接受的格式
;輸出:CF - CY 錯誤;NC 正常
;      ST - 若正常則 IEEE 實數;若錯誤則重設 FPU
        extrn   x_p_y_5c:near
        public  ascii_to_ieee_5c
ascii_to_ieee_5c        proc    near
        push    si              ;016 保存 SI
        call    real2           ;017 SI=此副程式所需資料之真正位址
addr2   equ     this word
real2:  pop     si
        sub     si,offset addr2

        push    ax              ;022 保存 AX、BX
        mov     cs:byte ptr status[si],0        ;023 設定沒有小數點、E、有效數
        push    bx
        cmp     byte ptr [bx],cr                ;025 檢查是否為空字串,及使用者
        jz      zero                            ;    僅輸入一個 0DH
        call    sign            ;   s   ;       ;027 取得有效數正負號
        call    get_num         ;   m   ;       ;028 計算有效數數值
        jc      error
        cmp     al,cr
        jz      ok

        and     cs:byte ptr status[si],0fdh
        call    sign            ;   s   ;   m   ;034 取得 10 的次方數之正負號
        call    get_num         ;   e   ;   m   ;035 計算 10 的次方數數值
        jc      error
        fild    cs:ten[si]      ;  10   ;   e   ;   m   ;
        call    x_p_y_5c        ; 10^e  ;   m   ;
        fmulp   st(1),st        ;m*10^e ;       ;039 得到 m*10^e 於 ST
ok:     clc                     ;040 正常結束
exit:   pop     bx
        pop     ax
        pop     si
        ret

zero:   fldz            ;046 使用者只輸入一個 0DH
        jmp     ok

error:  stc             ;044 錯誤結束
        finit
        jmp     exit
;---------------------------------------
;053 取得正負號之副程式
sign:   mov     al,[bx]
        fld1                    ; s=+1  ;
        cmp     al,'-'
        jz      sign_m
        cmp     al,'+'
        jz      sign_p
        ret
sign_m: fchs                    ; s=-1  ;
sign_p: inc     bx
        ret
;---------------------------------------
;065 檢查 AL 是否在 0-9 或 30H-39H 之間,若是則 NC 並使 AL 在 0-9;若否則 CY
check:  cmp     al,9
        jb      num
        sub     al,'0'
        jb      non_n
        cmp     al,9
        ja      non_n
num:    clc
        ret
non_n:  stc                     ;074 輸入字串含非數字,錯誤
        ret
;076 資料區---------------------------------------------------------------------
x       dw      ?       ;FPU 只能由記憶體載入數值,每一位數暫時存放此處再載入 FPU
ten     dw      10      ;常數 10
status  db      ?       ;bit0=0 無E符號  bit1=0 無小數點  bit2=0 無有效數
;                             1 有E符號       1 有小數點       1 有有效數
;-------------------------------------------------------------------------------
get_num:                                        ;082 計算數值之副程式
        fldz                    ;  i=0  ;   s   ;083 先載入 0
n0:     cbw                                     ;084 使 AH=0,以便存入 x 變數
        mov     al,[bx]
        cmp     al,cr
        jz      n2
        cmp     al,'E'
        je      n1
        cmp     al,'e'
        je      n1
        cmp     al,'.'
        je      n6
        call    check
        jnc     n7
        jmp     short n5

;098 處理輸入字串中含科學記號 E 之程式片段
n1:     test    cs:status[si],1         ;099 檢查是否已經有『E』了
        jnz     n5
        or      cs:status[si],1         ;101 還未有『E』,正確

;103 處理結尾符號 0DH
n2:     test    cs:status[si],0fh
        jz      na
        test    cs:status[si],2
        jz      n3                              ;107 如有小數點須先將 t 彈出
        fcomp   st(1)           ;   i   ;   s   ;108 彈出 t
n3:     test    cs:status[si],4                 ;109 檢查字串是否沒有有效數
        jnz     short n4
        fcomp   st              ;   s   ;       ;111 若無有效數,則設有效數為 1
        fld1                    ;  i=1  ;   s   ;
n4:     fmulp   st(1),st        ; m=i*s ;       ;113 使有效數值與正負號相乘
        inc     bx
        clc
        ret
n5:     stc
        ret

;120 處理字串中含小數點的程式片段
n6:     test    cs:status[si],2         ;121 檢查是否已經有小數點
        jnz     n5
        or      cs:status[si],6         ;123 還未有小數點
        fld1                    ;   1   ;   i   ;   s   ;124 ST=0.1,以後每增一
        fidiv   cs:ten[si]      ; t=0.1 ;   i   ;   s   ;    位小數,t 變為原來
        jmp     short n9                                ;    的十分之一

;128 處理字串中的『數』的程式片段
n7:     mov     cs:x[si],ax             ;129 存入暫時存放處
        or      cs:status[si],4         ;130 設定有有效數旗標
        test    cs:status[si],2         ;131 檢查此位數為整數部份或小數部份
        jnz     n8
;133 沒輸入小數點,故為整數部分
        fimul   cs:ten[si]      ; i=10i ;   s   ;       ;134 每增加一位數,
        fild    cs:x[si]        ;   x   ;   i   ;   s   ;    原數變 10 倍
        faddp   st(1),st        ;i=10i+x;   s   ;       ;136 加上新增的一位數
        jmp     short n9
;138 已輸入小數點,故為小數部分
n8:     fld     st              ;   t   ;   t   ;   i   ;   s
        fimul   cs:x[si]        ; x=x*t ;   t   ;   i   ;   s   ;140 新增一位小數
        faddp   st(2),st        ;   t   ; i=x+i ;   s   ;
        fidiv   cs:ten[si]      ;t=t/10 ;   i   ;   s
n9:     inc     bx
        jmp     n0

na:     fcomp   st
        fldz
        jmp     n4
ascii_to_ieee_5c        endp
;---------------------------------------
code    ends
;***************************************
        end     ascii_to_ieee_5c

把它寫好後存入 A2IEEE5C.ASM,組譯好並加入程式庫,MYASMLIB.LIB。

ascii_to_ieee_5c 程式說明

假想,您現在是一個使用者,要輸入一個數字,這個數字可能是像『12345』這樣的整數,也可能是像『0.003』或是像『-88.88』或是像『6.02×1023』這樣的數,所以這個副程式得考慮到所有使用者可能輸入的情況。

為了簡化程式,當使用者輸入像『6.02×1023』這樣的數時,10 的幾次方是用『E』來表示,而在『E』之前與『E』之後都應該是數字,所以小木偶設立一個副程式,get_num,來取得數字部份,這樣在取得有效數或 10 的次方數都只呼叫 get_num 就可以了。此外在數字之前也有可能包含正負號,所以在呼叫 get_num 之前先呼叫 sign 副程式來設定正負號,如果為正號或使用者沒有輸入則會在 ST 存入 +1,反之則為 -1。

接下來是這個程式最重要的部份,即數值的取得,也就是 get_num 那段程式片段 (第 82 行到第 148 行)。這段程式主要可分為兩部份,所輸入的數字字元是在整數部份或是在小數部份,假如是在整數部份,則原先的數必須變成 10 倍,然後再加上該數字;假如是在小數部份,則原先的數值不變,而新加入的數字要比變成原數值的最小位數還小十分之一。

舉例來說,如果使用者輸入『1234.567』這個字串,在記憶體中位址由低而高是『31 32 33 34 2E 35 36 37 0D』,最先處理的是整數部份的『1』,當處理到第二位,2,時原先的 1 變成 10 再加上 2,於是成 12,當處理到 3 時,原先的 12 變 120 再加上 3 成為 123……一直到整數數結束,在程式第 134 行就是使原數乘以 10。處理小數時,第一位,5,應該看成 0.1*5,第二位,6,應該看成 0.01*6……,所以小木偶在第 124、125 行設定 0.1,當每新增一位時,先乘以新增的數 (第 140 行),再加到原數就可算出數值部份了 (第 141 行),最後為了下一位數運算,還要把 0.1 再除以 10(第 142 行)。

其他值得提一提的大概是 status 變數了,這個變數是小木偶用來記錄『旗標』的。它的功用就類似 CPU 的旗標。status 的第零位元代表使用者輸入的字串是否包含『E』字元,小木偶先假設沒有『E』字元,該位元設為零(第23行),當程式讀取到『E』時再設該位元為一(第 101 行),但是如果使用者輸入兩個或兩個以上的『E』顯然是不合法的數字,於是再讀取到『E』時就得檢查是否已經有讀過『E』了(第 99 行),於是產生錯誤。

status 的第一位元是用來檢查小數點的,方法同上,也是先假設沒有輸入小數點,當遇到小數點時設定此位元為一,再遇到小數點時就產生錯誤。status 的第二位元是用來檢查使用者是否輸入『次方符號前毫無任何數字的字串』,例如『E02』這樣的字串,這類字串應該是省略有效數,1,這個副程式將它看成 100。小木偶先假設該位元為零,表示使用者所輸入的字串就是類似『E02』的這樣字串,但是只要有輸入任何有效數值,就會使該位元為一(第123、130行);假如都沒有遇到有效數字,那該位元會保持為零,所以程式 109 到 112 行檢查是否是這樣的情況,假如是這種情形,則有效數必須設為一。


測試 ieee_to_ascii_5c 與 ascii_to_ieee_5c

寫好這兩個副程式後,小木偶再寫個程式來測試它們,稱為 TSTIEEE.ASM (TST 是 test 之意)

;***************************************
code    segment
        assume  cs:code,ds:code
        org     100h
        extrn   ascii_to_ieee_5c:near
        extrn   ieee_to_ascii_5c:near
;---------------------------------------
start:  jmp     begin
string  db      50,0,50 dup (?)
num     db      0dh,0ah,26 dup (?),'$'
two     dw      2
mes     db      0dh,0ah,'Error!$'
begin:  mov     ah,0ah
        mov     dx,offset string
        int     21h
        finit
        mov     bx,offset string+2
        call    ascii_to_ieee_5c
        jc      error
        mov     bx,offset num+2
        call    ieee_to_ascii_5c
        mov     dx,offset num
        jmp     short pnt
error:  mov     dx,offset mes
pnt:    mov     ah,9
        int     21h
        int     20h
;---------------------------------------
code    ends
;***************************************
        end     start

寫好之後,進行下面組譯、連結:

H:\HomePage\SOURCE>masm tstieee; [Enter]
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.


  51498 + 365446 Bytes symbol space free

      0 Warning Errors
      0 Severe  Errors

H:\HomePage\SOURCE>link tstieee [Enter]

Microsoft (R) Personal Computer Linker  Version 2.40
Copyright (C) Microsoft Corp 1983, 1984, 1985.  All rights reserved.

Run File [TA2I5C.EXE]: [Enter]
List File [NUL.MAP]: [Enter]
Libraries [.LIB]: myasmlib [Enter]
Warning: no stack segment

H:\HomePage\SOURCE>exe2bin tstieee tstieee.com [Enter]

H:\HomePage\SOURCE>ta2i5c [Enter]
123456 [Enter] →輸入數字
+1.23456000000000000E+0005 → TSTIEEE 印出的科學記號
H:\HomePage\SOURCE>ta2i5c [Enter]
-0.000355 [Enter]→再測試一次
-3.55000000000000000E-0004

註一:除了本章的程式之外,當然也有其他的方法把 IEEE 格式的暫時實數轉換成 ASCII 字串,例如 SYMDEB 可以顯示各種實數格式,顯然其內必定包含此種程式的程式碼,小木偶也嘗試過追蹤它,也找到了這段程式碼,請參考附錄八


回到首頁到第二十四章到第二十六章