主頁 > 前端設計 > 為什么帶有IMUL的32位立即數在NASM中給出警告而在GCC中給出錯誤?

為什么帶有IMUL的32位立即數在NASM中給出警告而在GCC中給出錯誤?

2021-10-14 22:19:54 前端設計

我目前正在調查該imul指令的一些奇怪行為,因為官方英特爾手冊似乎與實際情況略有不同。

我注意到的第一件事是英特爾手冊不認為這個例子是正確的指令:

imul rax, 2

然而 GCC/GAS(帶有.intel_syntax noprefix)和 NASM 都毫無問題地接受了這個指令。使用objdump -d向我展示了這一點:

48 6b c0 02             imul   $0x2,%rax,%rax

這意味著它會被翻譯成不同的指令,實際上該指令記錄在手冊中。

我已經覺得這很奇怪,想知道為什么會這樣。我唯一能找到這個檔案的地方是在NASM 指令集中,而且奇怪的是,在imul英特爾手冊中的指令說明中。后者寫道:

  • 雙運算元形式——在這種形式下,目標運算元(第一個運算元)乘以源運算元(第二個運算元)。目標運算元是通用暫存器,源運算元是立即數、通用暫存器或記憶體位置。中間積(輸入運算元的兩倍)被截斷并存盤在目標運算元位置。

這與同一條指令的操作碼表不一致。

NASM指令集也有提到imul reg64, sbytedwordimul reg64, imm說明,這兩個我都不明白是什么意思。imm將意味著也可以使用 64 位立即數,不是嗎?sbytedword我不清楚的含義

現在到 32 位立即數:NASM 指令集提到,imul reg64, imm32而英特爾手冊和 NASM 集都提到imul r64, r/m64, imm32. 但是,通常當使用比目標運算元低的立即數時,英特爾手冊在操作碼表的描述列中特別提到了符號擴展。在這種情況下,它沒有被提及,所以我想知道如果我碰巧使用負 32 位立即數(換句話說,需要所有 32 位)會發生什么。

這是我測驗的匯編代碼:

        global  imm_test

        section .text

imm_test:
        mov     rax, rdi
        imul    rax, 0xFFDFFFFF
        ret

然后我從 C呼叫了imm_test函式:

#include <stdio.h>

int imm_test(int n);

int main() {
    printf("%d\n", imm_test(1));
    return 0;
}

If that 32-bit immediate were to be sign-extended, the value I would assume would have to be printed is -2097153, which, when using NASM to assemble and GCC to compile and link, is exactly what is printed.
And yet NASM gives me this warning:

test.asm:7: warning: signed dword immediate exceeds bounds [-w number-overflow]
test.asm:7: warning: dword data exceeds bounds [-w number-overflow]

However, looking at the disassembly again, the instruction is encoded exactly the way I would expect it to be:

48 69 c0 ff ff df ff    imul   $0xffffffffffdfffff,%rax,%rax

It's a 32-bit immediate sign-extended to 64-bit.

When I change the syntax of the assembly code to GAS's .intel_syntax noprefix like so:

        .intel_syntax noprefix
        .global  imm_test

        .text

imm_test:
        mov     rax, rdi
        imul    rax, 0xFFDFFFFF
        ret

and try to assemble this with the GNU assembler, I don't just get a warning, I get an error:

test.S: Assembler messages:
test.S:8: Error: operand type mismatch for `imul

Changing the imul instructions to the properly documented imul rax, rax, 0xFFDFFFFF version does not change anything.

So I'm wondering, why is the documentation for imul so inconsistent, and why are 32-bit immediates officially supported (and also work correctly), yet they give errors or warnings?

uj5u.com熱心網友回復:

匯編源使用,而不是立即位模式編碼

imul r64, r/m64, sign_extended_imm32或 imm8 是唯一具有 64 位運算元大小可用的形式1請參閱英特爾的手冊 ( https://www.felixcloutier.com/x86/imul ),因此0x0000_0000_FFDF_FFFF不可編碼。

但這就是0xFFDF_FFFF意思;與任何寫入數字的位值方式一樣,左側未寫入的位置假定為 0。

NASM 警告截斷,GAS 只是錯誤,并帶有一個不太有用的訊息,但在這兩種情況下,唯一的問題是常量的數值。隨著.intel_syntax noprefix燃氣, imul rax, rax, 0x7FDFFFFF組裝就好了。一個有符號的正 32 位數字不是問題。(高位 = 0。)

mov eax, 0xFFDF_FFFF是可編碼的,因為運算元大小是 32 位,所以源運算元是一個原始的 32 位值,它不會隱式地被符號擴展到 64 位。

作為執行mov到 EAX 的一部分,RAX 的高 32 位被清零可以將其視為零擴展到 64 位的常量,但這種擴展是作為在 x86-64 上寫入 32 位暫存器的 32 位指令的一部分發生的。 add eax, 0xFFDF_FFFF是一個更清楚的例子:它正在執行 32 位加法,將結果截斷為 32 位,然后將其寫入 EAX。隱式零擴展到 RAX 發生在添加之后的暫存器寫入期間,而不是在讀取輸入時。只有mov復制一個值不變,才有空間以不同的方式看待它。

無論哪種方式,匯編器都會理解您撰寫的完整值,并會告訴您是否無法將該值編碼為任何運算元大小的運算元。 請記住,匯編源使用,而不是機器代碼的位模式這是您使用匯編程式的部分原因。如果你的意思是0xFFFF_FFFF_FFDF_FFFF,你應該寫那個。


imul rax,2 是一個“單獨的形式”?

NASM(以及大多數其他的匯編包括天然氣)接受imul x, imm為短手imul x, x, imm對于 AVX 指令(如vpand xmm0, xmm0, xmm1.

當您不想利用非破壞性的單獨目的地時,它只是使您不必將相同的暫存器作為目的地和第一個源重復兩次。這種形式沒有不同的機器編碼,只有匯編級語法,這就是為什么你在英特爾的手冊中找不到它,以及為什么反匯編顯示匯編程式選擇的真實形式。


腳注 1: 您提到了NASM 附錄 B,其中顯示:

IMUL             reg64,reg64,imm8         X64 
IMUL             reg64,reg64,sbytedword   X64,ND 
IMUL             reg64,reg64,imm32        X64 
IMUL             reg64,reg64,imm          X64,ND 

我不知道這些ND條目的意義是什么,但它mov是 x86-64 中唯一可以立即執行 64 位指令的指令。imm8imm32形式是你的選擇一個完整的列舉。那么,sbytedword(有符號位元組或DWORD)。簡單的不合格imm只是令人困惑和錯誤。

(NASM 與reg64,reg64,imm8分開記錄形式reg64,imm8,這只是 NASM 讓中間運算元隱式與第一個運算元相同。機器編碼仍然imul r64, r/m64, immediate使用兩種不同的操作碼,一種用于 8 位,一種用于 32 位立即數。相同的操作碼做 32 位和 16 位運算元大小,沒有或不同的前綴。)

NASM 的附錄 B 以前是錯誤的,例如關于每個指令的每種形式是新的 CPU 版本 。NASM 2.05 附錄的這個分支糾正了這些錯誤,是一個有用的參考。它仍然包含更多的文本描述,當指令串列變長時,后來的 NASM 版本洗掉了這些描述。(但是,它只列出了 32 位和 16 位模式指令,沒有列出 64 位模式指令。)

但實際上,當我想檢查imul r,r/m,imm186是否是新的或類似的東西時,我只會參考 ecm 的 NASM 附錄的分支如果我想知道 x86 ISA 的當前狀態,可用的指令形式,我會查看 Intel 的手冊(或者實際上是從https://www.felixcloutier.com/x86/上的英特爾第 2 卷 PDF 中抓取的 HTML 。)英特爾有時會出錯,但不是關于手冊要點的重要/基本內容。

uj5u.com熱心網友回復:

為什么官方支持 32 位立即數(并且也可以正常作業),但它們會給出錯誤或警告?

我假設 64 位 GCC 編譯器在內部使用帶符號的 64 位整數。

我使用的版本會列印一條錯誤訊息,因為 64 位值 0xFFDFFFFF不在范圍內-0x80000000…… 0x7FFFFFFF因此無法轉換為 32 位有符號值!

注意:“支持 32 位常量”并不意味著如果需要超過 32 位,匯編器會自動將常量截斷為 32 位!并且您至少需要 33 位才能將值存盤0xFFDFFFFF為有符號數!

將常量寫入 as0xFFFFFFFFFFDFFFFFFFFF或 as-0x200001效果很好。

也許 NASM 的開發人員希望像這樣的數字0xFFFFFFFE被解釋為-2與舊程式兼容,-2可以寫成0xFFFFFFFE;

... GNU AS 的開發人員假設開發人員輸入0xFFFFFFFE64 位程式確實意味著 4294967294而不是-2

...這意味著 GAS 假設imul rax, rax, 0xFFDFFFFF應具有與imul rax, rbxa 之后相同的結果mov rbx, 0xFFDFFFFF

因此,GNU AS 會列印一條錯誤訊息,因為imul rax, rax, immediate不能rax相乘 4294967294

所以我想知道,為什么檔案imul如此不一致......

這與檔案無關:

GCC(和 GNU 匯編器)使用與 Intel 官方語法不同的語法。“nasm”更接近官方語法。

......我認為這是在某處記錄的。

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/313750.html

標籤:assembly x86-64 nasm gnu-assembler immediate-operand

上一篇:為什么要保存某些暫存器?如果沒有,會出現什么問題?[復制]

下一篇:澄清TST指令-ARM匯編

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more