簡體   English   中英

裝配中的平方根,如何移位和更改位

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM