2011-08-28 50 views
0

我有一個簡單的高級彙編程序,我正在學習位移和旋轉的來龍去脈。我有這個簡單的程序,可以在單個字節中移位。爲什麼沒有設置進位標誌?

static 
var: int8 := 127; 

begin test1; 

stdout.put(var, nl); 
shl(1, var); 
stdout.put(var, nl); 
if (@C) then stdout.put("carry set"); endif; 
end test1; 

由於字節設置爲127,應該通過左移一次是01111111

當然,作爲最後一位保留簽約進位標誌應提高?

然而,這並不是看起來會發生的事情,實際上所有的字節都會左移一次,因此字節現在是11111110或-2。

如果每次都發生這種情況,什麼情況會導致進位標誌置位?

平臺是贏得7 64位

+0

可能重複的[關於組件CF(進位)和(溢出)標誌(http://stackoverflow.com/questions/791991/ about-assembly-cfcarry-and-ofoverflow-flag) – Amber

+0

我認爲「轉移」的意圖是 – WaelJ

+0

@paul,對不起,我已經改變了代碼來反映我的問題。 –

回答

8

如前所述其他人則需要將127位乘以2位,以便進位標誌實際設置。但是你說它仍然不起作用;這是我最好的猜測原因:

我不熟悉HLA及其庫函數,但是,作爲編寫程序集時的一般規則,您應始終假定調用庫函數可能會更改任意方式,除非有一些文件另有說明。許多指令可以更改標誌,所以除非庫函數顯式保存了入口標誌並在退出時恢復標誌(例如通過將它們與pushf和指令一起保存在堆棧中),它們可以以任何狀態結束。

在你的代碼,您必須將shl和進位標誌的測試之間的stdout.put庫例程的調用:

shl(2, var); /* I'm assuming you've already changed 1 to 2 here */ 
stdout.put(var, nl); 
if (@C) then stdout.put("carry set"); endif; 

我猜stdout.put被清除標誌。

因此,嘗試後移把測試立即:

shl(2, var); 
if (@C) then stdout.put("carry set", nl); endif; 
stdout.put(var, nl); 
+0

是的,完美的,謝謝! –

0

看來你正在使用的移位指令是一個邏輯移位器,即它不會留下符號位不變。嘗試(在x86指令SAR和SAR)尋找一個算術移位指令

+0

不,算術左移是sal,這個shl是非算術移位指令。 –

+0

@Jason Sill:固定。謝謝 – WaelJ

+0

@WaelJ:爲什麼我在手冊中找不到任何'ras','las'說明? – phoxis

1

左(SAL)和換檔邏輯左移位運算(SHL)指令執行 相同的操作;他們將目標操作數中的位移到左邊(朝着更高有效位位置的 )。對於每個移位計數,該 目標操作數的最顯著位將移入CF標誌,最低顯著位清零

移位算術右移(SAR)和轉移邏輯右(SHR)指令將目標操作數的位 移到右側(朝向較低有效位位置)。對於每個 移位計數,目標操作數的最低有效位移入CF 標誌中,並且最高有效位根據指令 類型設置或清零。 SHR指令清除最重要的位(請參閱英特爾® 64和IA-32架構軟件開發人員手冊,第1卷中的圖7-8)。 SAR 指令設置或清除最高有效位,以對應目標操作數中原始值的符號(最高位爲 )。實際上,SAR 指令填充空位位置的移位值和未移位的符號 值

OF標誌僅在1位移位時受影響。對於左移,如果結果的最高有效位與CF標誌相同(即,原始操作數的前兩位 相同),OF標誌被設置爲0;否則,它被設置爲1.對於SAR指令,OF標誌被清除所有1位移位。對於SHR指令,OF標誌是 設置爲原始操作數的最高有效位。

CF標誌包含最後位的值移出所述目的地操作數的;對於SHL和SHR指令,其中的 未定義,其中計數大於或等於目標操作數的大小(以位爲單位) 。 OF標誌僅受1位移位的影響(參見上面的「說明」);否則,它是未定義的。根據結果​​設置SF,ZF和PF標誌 。如果計數爲0,則標誌不受影響。對於非零計數,AF標誌未定義。

UPDATE 這裏是什麼手冊告訴。僅用於設置CF和換檔操作循環體被示出:

IF instruction is SAL or SHL 
    THEN 
     CF ← MSB(DEST); 

    ELSE (* Instruction is SAR or SHR *) 
     CF ← LSB(DEST); 
FI; 
IF instruction is SAL or SHL 
    THEN 
     DEST ← DEST ∗ 2; 
    ELSE 
     IF instruction is SAR 
      THEN 
       DEST ← DEST/2; (* Signed divide, rounding toward negative infinity *) 
      ELSE (* Instruction is SHR *) 
       DEST ← DEST/2 ; (* Unsigned divide *) 
     FI; 
FI; 
tempCOUNT ← tempCOUNT – 1; 

根據上面DEST = 01111111SHL使得CF = MSB (DEST) = 0DEST = DEST * 2這是DEST = 127 * 2 = 254,其是二進制11111110和在2的補表示解釋它是-2十進制。

來源:Intel 64 and IA32 Architectures Software Developer Manual Volume 2

+0

這並沒有真正的幫助。從你粘貼的第一段(來源?),最重要的位應該已經移入CF標誌。但是,顯然這不會發生。 –

+0

在'01111111'的'var'結果中應用'shr'到'11111110'?所有的文字都是來源的副本,我已經在下面鏈接了。 – phoxis

+0

我應該注意我正在使用高級彙編語言,而不僅僅是彙編語言。所以進位標誌不應該設置爲127,但是-2是什麼?如果這些位是11111110,那麼由於MSB是1,所以進位標誌是否應該設置?如果我更改上面的代碼以將-2指定給var,則情況並非如此。無論我的操作是否MSB爲1,都設置了進位位。 –

1

最顯著位爲0 - 如果你想獲得一個1進位標誌,那麼就需要轉移由2位向左,即

shl(2, var); // [X] 01111111 -> [1] 11111100 
+0

即使我左移2,得到-4,進位位未被設置。 –