在下面的代碼中。如果我想訪問變數的單個位并將其與 1 進行比較。像 cmp ax,1 并保持將位的位置遞增 1 以獲得下一位,以便我可以計算該變數中設定為 1 的位數. 那可能嗎?
.data
var dw 1234
.code
uj5u.com熱心網友回復:
如果您的目標是 16 位或 32 位架構,這并不完全清楚。
一個一個地計算位的典型方法是這樣的:
mov cx, 1 // set mask bit
mov bx, 0 // initialise counter to accumulate bits
next_bit:
test ax, cx // check if the current bit is set, ZF==1 if not
jz skip_increment // if ZF==1, do not increment
inc bx
skip_increment:
add cx, cx // shift CX left by addition (8000h 8000h will overflow to zero)
jnz next_bit // if the mask did not yet overflow, continue loop
這個片段已經有很多優化:
- 我們不需要計算
1 << j, - 我們也不需要迭代次數
j - (0x8000 << 1) == 0的溢位,跳轉到回圈開始時檢測到
如果我們愿意丟棄ax,我們可以改為ax右移,好處是當沒有更多位ax可以計算時,我們可以立即跳出回圈。
mov cx, 0
next_bit: test ax, 1
jz skip_increment
inc cx
skip_increment:
shr ax, 1
jnz next_bit
我們能做得更好嗎?我們需要向前跳來跳過增量,這看起來效率不高。
xor cx, cx // another way to clear the counter register
next_bit:
shr ax, 1 // shift out the LSB in ax to carry
adc cx, 0 // increment with carry
test ax, ax // now we need to re-test ax for zero
jnz next_bit
奇怪的是,x86 指令集包含jcxz- 如果 cx==0 跳轉,但不是相反:如果 cx != 0 跳轉。如果是這樣,我們可以交換 ax 和 cx 的含義并跳轉到回圈的開頭,而無需額外測驗。
但是我們仍然可以重新排列回圈,以便我們復制一些代碼以允許回圈處理來自前一次和當前迭代的元素。
sub cx, cx // another way to clear cx, but also ensure CF==0
next_bit:
adc cx, 0 // add the carry from previous iteration
shr ax, 1 // move the LSB to carry, sets ZF, iff ax==0
jnz next_bit
adc cx, 0 // add the carry from last iteration
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/313738.html
上一篇:匯編中的At&t語法?
下一篇:如何在asm中使用MOV?
