為了更加清楚地讓我們知道,如何使用組合語言來實現這個函式,下面先以用c語言自己實現乙個itoa函式,再來說明使用組合語言實現方法及思想。因為無論是用c語言還是使用組合語言,其實現思想和方法都是一樣的,只是描述的語言不同。但是我們都比較熟悉c語言,而對組合語言並不是那麼的熟悉,所以為了讓我們更加好地理解這個函式的組合語言實現,我借助c語言的力量來模擬說明一下。
注:在本文**現的數字,「***」表示數字對應的字串,『x'表示單個數字對應的字元,x表示數字。
一、為什麼要把數字轉化成字串
在組合語言中,數字是不能直接輸出的,要想把數字輸出,就要將其轉換成字串(即字元)的形式,然後再以輸出字元的形式來輸出字串。這個就是我要用彙編實現這個函式的最初目的,就是輸出數字。當然,把數字轉化成字串還有很的實際的用途。
二、c語言的實現版本
如何把乙個數字轉化成乙個字串,即數字轉化成字串的演算法,在c語言中,相信大家都很熟悉。就是把數字一直除以10直到商為0,把餘數加上『0』的ascii碼,即可得到餘數的ascii碼,即數字對應的字元。例如:數字123,轉化成字串,其字元產生的次序就為『3』,『2』,『1』。最後,1除以10,商為0,餘數為1。
可以看到生成的字元的順序與真正的字串的順序是相反的,生成的字元應為「123」。因為32位的數字,最大也不過是10位數,所以我們只要申請乙個11個單元的陣列就肯定能放得下轉換後的字串,然而我們在轉化的時候,並不知道數字轉換成字串後,字串的長度為多少,也就是說,我們並不知道一開始產生的字元『3』要放在陣列的哪個地方,例如這裡的123的話,『3』應該放在下標為2的單元中,而如果數字是1243的話,『3』應該放在下標為3的單元中。
由於上面所說的兩個原因(產生的字元的順序與生成的字串的字元的順序相反、不能確定生成第乙個字元所在的單元位置),並考察棧的資料結構特徵,在實現的函式中,我們需要乙個棧。把生成的字元入棧,生成結束後,再把棧中的字元出棧,按順序放到字元陣列中,即可完成我們的功能。因為棧是先進後出的,所以『3』會最後出棧,這樣的話,產生的字串順序就與預想中的一樣。
itoa函式生成的字串是c風格的字串,即字串是以『\0』結束的,所以我們生成的字串也應是以字元『\0』結束。也就是說,『\0』才是字串的最後乙個字元。所以我們可以把『\0』先入棧,則它就會在最後出棧,放到字元陣列的最後。同時,它還能起到乙個標記的作用,也就是說,如果『\0』出棧,則說明所有產生的字元都已經放到字元陣列中,棧為空。
下面來看看它的實現**:
注:為了與itoa區別,這裡使用函式名,dtoc,意思為doublewordtochar,要放入的字串位址由引數str給出。void wtoc(int num, char *str)
dowhile(c != '\0'); //'\0'出棧,所有的字元都複製完結
destory(&s);
}這段**的做法與前面所說的實現思想完全相同,不再重複。stack是乙個我們自己定義的資料結構——棧,由於要與彙編中的操作相對應,這裡只有兩種操作,乙個是push,乙個是pop,除此之外,不提供任何操作。
三、組合語言的實現
下面再來看看用組合語言實現的對應的子程式,如下:;子程式名:dtoc
;功能:將dword型資料轉變為十進位制數的字串,字串以0為結尾
;引數: (ax)=dword型資料的低16位,(dx)=dword型資料的高16位
; ds:si指向字串的位址
;返回:無
dtoc:
push si
push cx
mov cx, 0 ;把0先壓入棧底
push cx
rem: ;求餘,把對應的數字轉換成ascii碼
mov cx, 10 ;設定除數
call divdw ;執行安全的除法
add cx, 30h ;把餘數轉換成ascii碼
push cx ;把對應的ascii碼壓入棧中
or ax, dx ;判斷商是否為0
mov cx, ax
jcxz copy ;商為0,表示除完
jmp rem ;否則,繼續相除
copy: ;把棧中的資料複製到string中
pop cx ;ascii碼出棧
mov [si], cl;把字元儲存到string中
jcxz dtoc_return ;若0出棧,則退出複製
inc si ;指向下乙個寫入位置
jmp copy ;若0沒出棧,則繼續出棧複製資料
dtoc_return:;恢復暫存器內容,並退出子程式
pop cx
pop si
ret彙編子程式說明:
1、我們可以看到匯程式設計序並不比上面的c語言程式複雜多少,這個我們應該值得高興。
兩個程式中,我都用空行把它分割為5部分,組合語言子程式的第2、3、4部分,分別對應c語言程式中的第2、3、4部分。在上面的子程式中,我們使用了系統提供給我們的棧,而沒有自己去定義乙個,因為數字的個數並不多,最多也只有10個,所以我們可以放心地使用系統提供給我們的棧。
2、為了使操作統一,並讓除法不產生溢位而影響我們的結果,統一使用上一篇部落格——編寫無溢位除法的彙編子程式,中的divdw子程式來進行除法,而不直接使用div指令,若要轉化的數字只有16位,可在高位置0,使其成為32們的dword型別的數字。由於上一篇部落格有詳細的說明,這裡就不再說明了,它實現的是被除數為32位,除數為16位的無溢位除法。它的功能使用說明如下:
子程式名稱:divdw
功能:進行不會產生溢位的除法運算,被除數為dword型
除數為word型,結果為dword型
引數: (ax)=dword型資料的低16位
(dx)=dword型資料的高16位
(cx)=除數
返回: (dx)=結果的高16位,(ax)=結果的低16位
(cx)=餘數
3、標號為rem到到指令jmp rem之間標記的內容相當到c語言實現中的第乙個迴圈,即while迴圈,標號copy到指令jmp copy之間的內容相當到c語言中的第二個迴圈,即do while迴圈。
4、add cx, 30h,表示把cx中的餘數(數字)轉變成字元,因為,『0』的ascii碼為30h。
5、mov cx, 0
push cx ;把0先壓入棧底
實現就是一開始就把字元'\0'壓入棧中,用於在字串的最後面加入'\0',並用作所有字元都已經出棧的標記。
字串轉化為數字
如何把entry中輸入的字串轉化為對應的數字 例如,如果輸入為s 0 12 3 40 怎麼把它轉化為對應的數字呢?根據需要,胡亂寫了 記錄在此。功能 把字串轉化為數字列表 輸入s 字串 輸出 數字列表 def strtonum s s 0 12 3 40 p 用來存放字串中的數字 0,1,2,3,4...
將數字轉化為字串
將數字轉化為字串 方法一 include int main void temp 0 scanf d num number num do while number 0 string i 0 printf number d,位數是 d位 n num,i 統計出位數 for j 0,i j i 2 j i...
字串轉化為陣列,陣列轉化為字串。
做題中常遇到字串轉化為數字,數字轉化為字串等,自己轉化比較麻煩,c語言提供了幾個標準庫函式,可以將任意型別 整型 長整型 浮點型等 的數字轉換為字串。1.整數轉化為字串。itoa include include int main itoa 函式有3個引數 第乙個引數是要轉換的數字,第二個引數是要寫入...