x86-64 中 movq 和 movabsq 的区别

2024-02-23

我说的是 x86-64 Intel 架构中的数据移动指令。我读过,常规的movq指令只能具有可表示为 32 位二进制补码数的立即源操作数,而movabsq指令可以将任意 64 位立即数作为其源操作数,并且只能将寄存器作为目标。

您能详细说明一下吗?这是否意味着我可以使用以下命令移动 64 位立即值movabsq仅指令?并且只能从立即值到寄存器?我不知道如何将 64 位立即值移至内存。或者也许我在这里弄错了一些重要的事情。


除非您的 64 位值可以编码为 32 位符号扩展立即数,否则您必须先将其移至寄存器,然后再存储。 (或者进行两个单独的 32 位存储,或者使用其他更糟糕的解决方法来将字节获取到您想要的位置。)


在 NASM / Intel 语法中,mov r64, 0x... picks MOV编码 http://www.felixcloutier.com/x86/MOV.html基于常数。有四种立即数操作数可供选择:

  • 5 byte mov r32, imm32. (像往常一样进行零扩展以填充 64 位寄存器 https://stackoverflow.com/questions/11177137/why-do-most-x64-instructions-zero-the-upper-part-of-a-32-bit-register)。美国电话电报公司:mov/movl
  • 6+ byte mov r/m32, imm32。仅对内存目的地有用。美国电话电报公司:mov/movl
  • 7+ byte mov r/m64, sign-extended-imm32. 可以存储8个字节到内存,或将 64 位寄存器设置为负值。美国电话电报公司:mov/movq
  • 10 byte mov r64, imm64。 (这是与以下相同的 no-ModRM 操作码的 REX.W=1 版本mov r32, imm32) 美国电话电报公司:movabs, or mov / movq具有宽常数。

(字节计数仅适用于寄存器目标,或不需要 SIB 字节或 disp8/disp32 的寻址模式:只需操作码 + ModR/M + imm32,如mov dword [rdi], 123)

一些 Intel 语法汇编程序(但不是 GAS,除非您使用as -Os or gcc -Wa,-Os) 将优化 32 位常量,例如mov rax, 1至 5 字节mov r32, imm32(NASM 就是这样做的),而其他的(如 YASM)将使用 7 字节mov r/m64, sign-extended-imm32。他们都只对大常量选择imm64编码,而不必使用特殊的助记符。

或者用一个equ不幸的是,即使常量很小,YASM 有时也会使用 10 字节版本。


在具有 AT&T 语法的 GAS 中

movabsq意味着机器代码编码将包含一个 64 位值:要么是立即数,要么是绝对内存地址。(还有另一组特殊形式mov从绝对地址加载/存储 al/ax/eax/rax,并且 64 位版本使用 64 位绝对地址,而不是相对地址。 AT&T 语法调用该movabs以及,例如movabs 0x123456789abc0, %eax).

即使数量很小,例如movabs $1, %rax,您仍然获得 10 字节版本。

其中一些内容在本文中有所提及x86-64 指南中的新增内容 http://web.archive.org/web/20160609221003/http://www.x86-64.org/documentation/assembly.html使用 AT&T 语法。


但是,那mov助记符(带或不带q操作数大小后缀)将在之间进行选择mov r/m64, imm32 and mov r64, imm64取决于立即数的大小。 (看,存在一个后续问题,因为这个答案的第一个版本猜测了 GAS 对大汇编时间常量所做的事情是错误的movq.)

但是符号地址直到链接时才知道,因此当汇编器选择编码时它们不可用。至少在针对 Linux ELF 目标文件时,GAS 假设如果您没有使用movabs,您打算使用 32 位绝对值。 (YASM 对mov rsi, string具有 R_X86_64_32 重定位,但 NASM 默认为movabs,产生 R_X86_64_64 重定位。)

如果出于某种原因您想要使用符号名称作为绝对立即数(而不是通常更好的 RIP 相对 LEA),您确实需要movabs

(在 OS X 上的 Mach-O64 等目标上,movq $symbol, %rax可能总是选择 imm64 编码,因为 32 位绝对地址永远无效。有一些关于 SO 的 MacOS 问答,我认为人们说他们的代码可以使用movq将数据地址放入寄存器中。)


Linux/ELF 上的示例$symbol即时

mov    $symbol, %rdi     # GAS assumes the address fits in 32 bits
movabs $symbol, %rdi     # GAS is forced to use an imm64


lea    symbol(%rip), %rdi  # 7 byte RIP-relative addressing, normally the best choice for position-independent code or code loaded outside the low 32 bits

mov    $symbol, %edi    # optimal in position-dependent code

用 GAS 组装成目标文件(带有.bss; symbol:),我们得到这些搬迁。注意之间的区别R_X86_64_32S(签名)对比R_X86_64_32(无签名)对比R_X86_64_PC32(相对于 PC)32 位重定位。

0000000000000000 <.text>:
   0:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi        3: R_X86_64_32S .bss
   7:   48 bf 00 00 00 00 00 00 00 00   movabs $0x0,%rdi        9: R_X86_64_64  .bss
  11:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # 18 <.text+0x18>  14: R_X86_64_PC32       .bss-0x4
  18:   bf 00 00 00 00          mov    $0x0,%edi        19: R_X86_64_32 .bss

链接到非 PIE 可执行文件(gcc -no-pie -nostdlib foo.s),我们得到:

4000d4:       48 c7 c7 f1 00 60 00      mov    $0x6000f1,%rdi
4000db:       48 bf f1 00 60 00 00 00 00 00   movabs $0x6000f1,%rdi
4000e5:       48 8d 3d 05 00 20 00      lea    0x200005(%rip),%rdi     # 6000f1 <__bss_start>
4000ec:       bf f1 00 60 00            mov    $0x6000f1,%edi

当然,由于 32 位绝对重定位,这不会链接到 PIE 可执行文件。movq $symbol, %rax无法正常工作gcc foo.S在现代 Linux 发行版上. x86-64 Linux 中不再允许使用 32 位绝对地址? https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux。 (请记住,正确的解决方案是与 RIP 相关的 LEA,或者制作静态可执行文件,而不是实际使用movabs).


movq始终是 7 字节或 10 字节形式,所以不要使用mov $1, %rax除非您想要更长的指令用于对齐目的(而不是稍后用 NOP 填充)。可以使用哪些方法来有效地扩展现代 x86 上的指令长度? https://stackoverflow.com/questions/48046814/what-methods-can-be-used-to-efficiently-extend-instruction-length-on-modern-x86). Use mov $1, %eax得到5字节的形式。

请注意movq $0xFFFFFFFF, %rax不能使用 7 字节形式,因为它不能用符号扩展32 位立即数,需要 imm64 编码或%eax目的地编码。 GAS 不会为您进行此优化,因此您只能使用 10 字节编码。你一定想要mov $0xFFFFFFFF, %eax.

movabs具有直接来源的始终是 imm64 形式。

(movabs也可以是MOV编码 http://www.felixcloutier.com/x86/MOV.html使用 64 位绝对地址和 RAX 作为源或目标:就像REX.W + A3 MOV moffs64, RAX).


我不知道如何将 64 位立即值移至内存。

这是一个单独的问题,答案是:你不能。这MOV 的 insn ref 手动输入 http://www.felixcloutier.com/x86/MOV.html清楚地表明:具有 imm64 立即数操作数的唯一形式仅具有寄存器目标,而不是 r/m64。

如果您的值适合符号扩展的 32 位立即数,movq $0x123456, 32(%rdi)将在内存中存储 8 字节。限制是高 32 位必须是位 31 的副本,因为它必须可编码为符号扩展的 imm32。

Related:

  • 为什么我们不能将 64 位立即值移至内存? https://stackoverflow.com/questions/62771323/why-we-cant-move-a-64-bit-immediate-value-to-memory/62772299#62772299- 计算机体系结构/ISA 设计原因。
  • 如何将函数或标签的地址加载到寄存器中 https://stackoverflow.com/questions/57212012/how-to-load-address-of-function-or-label-into-register(使用 5 字节mov r32, imm32作为一种优化,或任何情况下与 RIP 相关的 LEA,除了符号可能超过 2GiB 的大内存模型。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

x86-64 中 movq 和 movabsq 的区别 的相关文章

  • 自定义键盘中断处理程序

    我正在尝试编写一个简单的程序 将标准键盘中断替换为自定义的键盘中断 以减少变量 但是 如果不调用旧处理程序 它就无法工作 这是我的中断处理程序 handler proc push ax push di dec EF pushf when t
  • 内联汇编中的内存偏移

    在 A64 汇编器中 有不同的方法来指定地址 base 0 Simple register exclusive Immediate Offset base imm Offset Immediate Offset base Xm LSL im
  • 不知道如何一次打印整个日历[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 cseg segment assume cs cseg ds cseg org 100H begin mov es cs video mov
  • x86 Assembly:很难找到无限循环挑战的想法

    我打算和我的朋友们进行一场类似于 corewars 的比赛 我们使用与原始游戏相同的内存网格 在游戏中 我们每个人都应该写一个 保险箱 它是一个不超过 25 行的无限循环 每个 安全 都有一个技巧或代码可以停止循环 从而破坏 安全 例如 S
  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • 如何获取 VESA BIOS 信息

    我正在跟踪Phil Opp 教程 https os phil opp com 关于用 Rust 编写一个操作系统 在稍微尝试了一下之后 我想在屏幕上显示真实的图形 我发现我应该从使用带有 VESA 的线性帧缓冲区开始 我在 osdev or
  • MASM 字符串反转

    好吧 我正在讨论这个问题 可能是一个非常复杂的解决方案 但这是我脑海中浮现的第一件事 我需要编写一个汇编语言程序来反转 源 字符串 而不使用 目标 字符串 临时变量 这是我的尝试 INCLUDE Irvine32 inc data sour
  • 装配中出现奇怪的字符?

    我写了以下代码 386 model small stack 100h data text db Paper 0 code start lea dx text mov ah 9h int 21h mov ah 4ch int 21h end
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • 在 REP MOVSW 之前 PUSH CS / POP DS 的目的是什么?

    为什么在下面的代码中我们压入代码段 PUSH CS 然后将其弹出到数据段 POP DS 我将这些行明确指定为 line1 和 line2 请告诉我 MOVSW 在这里是如何工作的 IF HIGHMEMORY PUSH DS MOV BX D
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • orpd等SSE2指令有什么意义?

    The orpd指令是 压缩双精度浮点值的按位逻辑或 这不是做完 全相同的事情吗por 按位逻辑或 如果是这样 拥有它还有什么意义呢 请记住 SSE1orps https www felixcloutier com x86 orps首先 实
  • 在 x86 程序集中将整数打印到控制台

    当我在 16 位汇编中添加两个值时 将结果打印到控制台的最佳方法是什么 目前我有这个代码 CODE START mov ax 1 put 1 into ax add ax 2 add 2 to ax current value mov ah
  • 汇编-符号标志和奇偶校验标志

    我不明白什么时候设置标志标志 什么时候设置奇偶校验 据我所知 符号标志表示运算结果的符号 0表示正数 1表示负数 那么为什么在下一个代码中 mov al 5 sub al 124 SF为零 结果是负数 关于PF 为什么a和b中设置了PF a
  • 为什么不能执行 mov [eax], [ebx] [重复]

    这个问题在这里已经有答案了 我可以做这个 mov eax ebx 和这个 mov eax ebx 甚至这个 mov eax ebx 但不是这个 错误C2415 mov eax ebx 只是wtf 为什么 它与 ptr1 ptr2 相同 为什
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外
  • Visual Studio 2017 上的简单装配程序

    386 model flat c stack 100h printf PROTO arg1 Ptr Byte data msg1 byte Hello World 0Ah 0 code main proc INVOKE printf ADD
  • 汇编基础知识:输出寄存器值

    我刚刚开始学习汇编语言 我已经陷入了 在屏幕上显示存储在寄存器中的十进制值 的部分 我使用 emu8086 任何帮助将不胜感激 model small Specifies the memory model used for program
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 近调用/跳转表并不总是在引导加载程序中工作

    一般问题 我一直在开发一个简单的引导加载程序 并在某些环境中偶然发现了一个问题 在这些环境中 此类指令不起作用 mov si call tbl SI Call table pointer call call tbl Call print c

随机推荐

  • JS 字符串:替换为正则表达式中的索引

    我对正则表达式几乎没有经验 我想知道如何替换由正则表达式标识的字符串中的部分 其中索引是标识部分的一部分 这是我的示例字符串 let exampleStr How do I 0 the n with the 1 in my array 这是
  • 启用 nginx 分块传输编码

    看起来像nginx 0 8 35 可能支持分块传输编码 http nginx org en CHANGES 2010 年 4 月 1 日 nginx 0 8 35 的变化 Change now the charset filter runs
  • 项目参考与文件参考?

    可以通过两种方式在项目中添加引用 项目参考 文件参考 但是 什么时候使用 Project 什么时候使用 File 引用 您没有指定 但我猜您指的是 Visual Studio 项目引用和文件引用之间的主要区别在于是否提供实时更新 在项目参考
  • SASS中有多行吗? [复制]

    这个问题在这里已经有答案了 我无法从 SASS 文档中弄清楚这一点 例如我想使用带有 5 个参数的 Compass mixin link colors normal hover false active false visited fals
  • 如何在Meteor服务器中获取用户IP地址?

    我想在我的流星应用程序中的服务器端获取用户IP地址 以便我可以用一堆东西记录IP地址 例如 订阅邮件列表的非注册用户 或者只是做任何事情 重要的 我知道 当涉及反向代理时 服务器 看到 的 IP 地址可能与真实源地址不同 在这种情况下 X
  • MYSQL 中的规范化

    MySQL 中的规范化是什么 在什么情况下以及如何使用它 我尝试在这里用外行术语来解释标准化 首先 它适用于关系数据库 Oracle Access MySQL 因此它不仅仅适用于 MySQL 规范化是为了确保每个表具有唯一的最小字段并消除依
  • uint32_t 与 int 作为日常编程的约定

    什么时候应该使用 stdint h 中的数据类型 总是使用它们作为惯例是正确的吗 像 int 和 Short 这样的非特定大小类型的设计目的是什么 什么时候应该使用 stdint h 中的数据类型 当编程任务指定整数宽度时 特别是为了适应某
  • 在 Facebook 等 iOS 应用程序中预览嵌入链接

    我正在尝试以与 Facebook 相同的方式在 iOS 应用程序中嵌入链接预览 我正在尝试找到一种方法来获取最合适的图像 并返回其 url 页面标题 甚至可能是元描述并将其传递回应用程序 但我不确定最好的方法 有一些 API 可以做到这一点
  • 在 Tkinter 中拖放?

    在 tkinter 中完成拖放的正确 官方 正确 推荐的方法是什么 我的文档第 24 1 1 节包括 Tkdnd 对 Tkinter 的拖放支持 这是实验性的并且 当它被 Tk DND 取代时 它应该被弃用 但我找不到其他的official
  • 正则表达式仅允许数字或空字符串

    有人可以帮我创建这个正则表达式吗 我需要它来检查字符串是否完全是空白 空 或者是否只包含正整数 如果还有其他事情 那就失败了 这是我到目前为止所拥有的 s 0 9 0 9 您正在寻找 s d 如果您想要一个不带前导零的正数 请使用 1 9
  • 如何使用 Expo EAS 为 React Native 中的 组件启用动画 webp?

    使用 Expo EAS 构建时 动画 gif 在 Android 中可以工作 但动画 webp awebp 则不能 Why 如何让 awebp 工作 为什么 gif 动画可以用 但它却不起作用 React Native 有动画图像支持多种格
  • IntelliJ IDEA 和 Gradle:为什么每个子模块有 3 个模块?

    我对 IntelliJ IDEA 的 gradle 集成以及 gradle 子项目到 IDEA 模块的映射感到相当困惑 为什么每个 gradle 子项目都有 3 个模块 client client main 和 client test 有没
  • 停止异步 ISearchJob 的正确方法

    我要使用WUA API https msdn microsoft com en us library windows desktop aa387099 v vs 85 aspx并以这种方式开始执行异步搜索更新 CComPtr
  • python中比较两个列表的最佳算法

    我在 python 中有两个列表 list1 和 list2 其中填充了自己的数据类型 我想将它们与列表进行比较 并将这些列表的所有元素提供给标准输出 或其他地方 但以特定的顺序 不以任何方式对列表进行排序 List1 和 List2 可以
  • 通过 go-mssqldb 进行 golang SQL Server 查询

    我正在尝试查询SQL Server 2008 R2使用去 https github com denisenkom go mssqldb https github com denisenkom go mssqldb SQL Server 20
  • 不存在的目录/文件 Web API(非控制器)的自定义错误页面

    我知道我可以为不存在的控制器或错误的路由设置自定义错误页面 但是如果用户尝试下载某个目录中不存在的文件 如何显示自定义错误页面 我根本无法让它发挥作用 它仍然显示默认错误页面 这篇博文将引导您处理 ASP Net Web API 中的 40
  • 在浏览器中显示 Xquery (.xq) 文件

    我对编程很陌生 对 xml xquery 也很陌生 我有一个 xq 文件 带有 html 和 xquery 代码 和 xml 文件 用于存储数据 在测试时 我可以使用 stylus studio 查看 xq 页面的显示方式 但我无法使用网络
  • MPlayer 如何识别 MJPEG 流?

    由于 MJPEG over http 基本上包括传输由定义的分隔符分隔的一系列 JPEG 图像 MPlayer 如何识别它是 MJPEG 流 谢谢 看一下 MplayerMjpegStreamViewing http www lavrsen
  • web.config 反斜杠出现两次 Visual Studio 2010

    我有一个在 Visual Studio 2008 中制作的 asp net Web 应用程序 一切都工作得很好 直到我切换到 VS 2010 当发生这种情况时 我开始看到数据库连接字符串出现一些奇怪的行为 该字符串 已编辑 但格式相同 如下
  • x86-64 中 movq 和 movabsq 的区别

    我说的是 x86 64 Intel 架构中的数据移动指令 我读过 常规的movq指令只能具有可表示为 32 位二进制补码数的立即源操作数 而movabsq指令可以将任意 64 位立即数作为其源操作数 并且只能将寄存器作为目标 您能详细说明一