[英]Square root in assembly, how to shift and change bits
我想在匯編中編寫一個快速的整數平方根算法,它需要無符號的32位。 我一直在閱讀過此 ,並有了一個主意。 這是我的偽代碼:
res <- 0
for i from 15 downto 0 do:
change the ith bit of result to 1
if res^2 > x then:
change the ith bit of res back to 0
return res
到目前為止,我已經完成了:
sqrt:
movl $0, %eax
movl $15, %edx
jmp .L8
.L9
.L8
cmpq cmpq $0, %edx
jge .L9
我陷於for循環操作中,更改了ith位並進行了移位。 我也不想使用除法或sqrt指令。 我知道我應該使用shr
,但是我不知道從哪里開始或如何做。 我該如何在for循環中進行操作? 我從哪里開始?
(Intel語法,自行轉換為AT&T)
mov ebx,<number> ; *number* to find sqrt of
mov ecx,0x8000 ; bitmask (starting with b15 bit set)
;^^^ 0x8000 = decimal 32768 = binary 1000 0000 0000 0000
xor eax,eax ; result <- 0
sqrt_loop:
xor eax,ecx ; set bit in eax
push eax ; store result (will be destroyed by mul)
mul eax ; edx:eax <- eax*eax (ignoring edx next)
cmp eax,ebx ; compare with *number*
pop eax ; restore result
jbe keep_bit ; res^2 <= *number* -> bit stays set
xor eax,ecx ; unset bit in eax
keep_bit:
shr ecx,1 ; next bit
jnz sqrt_loop ; loop till all bits are tried
(我沒有嘗試過+對其進行調試,所以可能存在一些錯誤。但是我認為,與您的偽算法以及通過調試重寫到AT&T一起,這應該足以使您入門。)
正如瑪格麗特指出的那樣,數字就是數字,這就是價值。 因此0x8000已經在CPU導線中編碼為b15設置為1,其他位設置為0。當您想將值從字符串轉換為字符串時,所有的轉換工作都會發生,但是只要您使用值進行計算,它就會存在同時以各種形式注冊。 這取決於您如何看待寄存器。 在源代碼中使用十六進制/十進制/二進制是這樣的:編寫數字的STRING表示形式,匯編程序將其轉換為值本身。
二進制表示形式是特殊的,因為CPU可以尋址特定的位(具有和/或,和,或旋轉,位測試/設置等),因為它具有那些以“電線”形式存在的值,並且是其本機表示形式。 就像人類在計算“ 10 * 3456”時在“作弊”時,最后只寫額外的0以獲得結果一樣,因為十進制格式就是10 *的特殊之處。 對於CPU,同樣的情況發生在位操作和2數學的各種功效上。 但是十進制技巧是不可能的,那些具有CPU以正確的方式進行計算,實際乘以10。
無論如何,當您只有位數時,並且想要獲取位掩碼本身,例如如何從15中獲取0x8000:
mov ecx,15 ; i-th bit
mov eax,1 ; set b0 (lowest bit)
shl eax,cl ; shift all bits (all zeroed + b0 set) cl-many times left
; eax now contains 0x8000 = b15 set, other bits zeroed
因此,如果您堅持使用算法的方法,則每次都必須重新計算for計數器到位掩碼(或使用一些位設置/重置指令,我從頭開始並不知道,因為幾乎不需要它們)。
但是,如果您學習我的代碼,您會發現有直接的快捷方式可以在位掩碼本身上工作,而無需計算“第i個位”部分,從而使代碼更短,更快(盡管我可能是通過push / pop殺死了它,也許再使用一個像esi
這樣的寄存器來存儲值會更好...然后再次說明如何使用堆棧,以及標志如何不受某些指令的影響,因此,如果您願意,可以延遲使用cmp
結果請注意不要修改必需的標志)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.