问题标签 [immediate-operand]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
cpu - CPU 需要多少内存引用来执行立即地址指令,为什么?
在立即寻址模式下,我知道在指令本身中我们有操作数的值,而不是操作数的地址。那么,CPU 是否需要任何内存引用,因为操作数的有效地址是指令本身的地址。
任何见解都会非常有帮助。
assembly - 使用 Arm 内联 GCC 程序集立即加载 16 位(或更大)
注意:为了简洁起见,这里的例子被简化了,所以它们不能证明我的意图。如果我只是像示例中那样写入内存位置,那么C 将是最好的方法。但是,我正在做的事情在这个例子中我不能使用 C,即使一般来说最好留在 C 中。
我正在尝试使用值加载寄存器,但我坚持使用 8 位立即数。
我的代码:
https://godbolt.org/z/8EE45Gerd
当我编写 C 代码(请参阅a()
参考资料)时,它会在 Godbolt 中组装成:
我认为它使用MOV
as 伪指令。当我想在汇编中做同样的事情时,我可以将值放入某个内存位置并使用LDR
. 我认为这就是我使用 -march=ARMv7E-M (MOV
替换为LDR
)时 C 代码的组装方式,但是在许多情况下,这对我来说并不实用,因为我会做其他事情。
在 0x21014 地址的情况下,前 2 位为零,因此当我正确移位它时,我可以将这个 18 位数字视为 16 位,这就是我在 中所做的b()
,但我仍然必须通过它8 位立即数。但是,在 Keil 文档中,我注意到提到了 16 位立即数:
https://www.keil.com/support/man/docs/armasm/armasm_dom1359731146992.htm
https://www.keil.com/support/man/docs/armasm/armasm_dom1361289878994.htm
在 ARMv6T2 及更高版本中,ARM 和 Thumb 指令集都包括:
最低有效一半的内容。
我认为我的 CortexM4 应该是 ARMv7E-M 并且应该满足这个“ARMv6T2 及更高版本”的要求,并且应该能够使用 16 位立即数。
但是,从 GCC 内联汇编文档中,我没有看到这样的提及:
https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
当我启用 ARMv7E-M 架构并取消注释c()
我使用常规“I”立即的位置时,我得到一个编译错误:
所以我想知道有没有办法在 GCC 内联汇编中使用 16 位立即数,或者我是否遗漏了一些东西(这会使我的问题无关紧要)?
附带问题,是否可以在 Godbolt 中禁用这些伪指令?我已经看到它们也与 RISC-V 程序集一起使用,但我更愿意查看反汇编的真实字节码,以了解这些伪/宏程序集指令产生的确切指令。
c - C/SIMD - 创建一个“立即数组”;返回立即值的数组?
我的意思是使用类似于上面的代码来左打包一个浮点数组,将比较传递给另一个,但它返回错误'最后一个参数必须是 8 位立即数。'我怎样才能做到这一点?
assembly - 检测立即 32 位操作数 (imm32) 的潜在 MASM 64 位符号扩展错误
我正在尝试编写一个工具来扫描 64 位汇编代码以查找可能的符号扩展错误。
例如,假设一个 32 位常量 (imm32) 定义为
接下来,调用任何返回 SOCKET_ERROR(32 位整数)的 API,并将结果存储在 64 位变量retval中。但是,将retval与 SOCKET_ERROR_INT 进行比较会生成
请注意 SOCKET_ERROR_INT (imm32) 符号扩展为 64 位!(见下表:cmp m64, imm32)但是,qword ptr [rbp-8]是0FFFFFFFFh ( retval ),所以比较阴险地失败了!
笔记
立即操作数 (imm32) 是常量值或常量表达式的结果。汇编器在汇编时将立即值编码到指令中。
在某些情况下,MASM 表达式计算器会自动对数字进行符号扩展。符号扩展只能影响从0x80000000到0xFFFFFFFF的数字。也就是说,符号扩展只影响可以写入 32 位且高位等于 1 的数字。
例如,当调试器将其视为 64 位数字时,数字 0x12345678 始终保持为 0x0000000012345678。另一方面,当 0x890ABCDE 被视为 64 位值时,它可能会保持 0x00000000890ABCDE 或 MASM 表达式评估器可能会将其符号扩展为 0xFFFFFFFF890ABCDE。
这是符号扩展的指令的不完整列表:
offset64.asm
要构建示例,请创建一个makeit64.bat,如下所示:
运行批处理文件会创建此输出。(没有警告或错误)
沉默的 MASM
没有警告、错误和跳转等于 FALSE。例如,
生成
问题:是否有完整的易于签名扩展的指令列表?
assembly - 在 ARM 汇编中编译 MOV 指令时出错
我正在使用 RVDS6_13 编译器,我的处理器是 Cortex X1 (HERA)。对于需要进行一些汇编语言编程的测试,我在编译时遇到以下错误:
错误:A1616E:当前指令集不支持指令、偏移量、立即数或寄存器组合 9 00000000 MOV x28,0xD02E7F30
基本上我需要加载 0xB41138A4 到地址位置 0xD02E7F30,下面是我的代码:
assembly - 将单词与即时价值进行比较?
我正在努力掌握如何在 MIPS 中操作/比较存储在寄存器(字/半字/中间值)中的数据。如果它们各自代表不同的字节数有关系吗?例如,通过li加载一个立即数比如5,然后加载一个比如5的单词,最后用bne进行比较是否有效?
assembly - 为什么 IMUL 的 32 位立即数会在 NASM 中给出警告而在 GCC 中给出错误?
我目前正在调查该imul
指令的一些奇怪行为,因为英特尔官方手册似乎与现实略有不同。
我注意到的第一件事是英特尔手册不认为这个例子是正确的指令:
然而 GCC/GAS (with .intel_syntax noprefix
) 和 NASM 都毫无问题地接受这个指令。使用objdump -d
向我展示了这一点:
这意味着它被翻译成实际上记录在手册中的不同指令。
我已经觉得这很奇怪,并且想知道为什么它会存在。我唯一能找到这个文档的地方是在NASM 指令集中,而且奇怪的是,在imul
英特尔手册中的指令描述中。后者写道:
- 双操作数形式— 使用这种形式,目标操作数(第一个操作数)乘以源操作数(第二个操作数)。目标操作数是通用寄存器,源操作数是立即数、通用寄存器或内存位置。中间产品(输入操作数大小的两倍)被截断并存储在目标操作数位置。
这与同一条指令的操作码表不一致。
NASM指令集也提到imul reg64, sbytedword
和imul reg64, imm
指令,我都不明白它们的意思。imm
这意味着也可以使用 64 位立即数,不是吗?sbytedword
我不清楚的含义。
现在到 32 位立即数:NASM 指令集提到imul reg64, imm32
,而英特尔手册和 NASM 集都提到imul r64, r/m64, imm32
。但是,通常当使用比目标操作数低的位计数的立即数时,英特尔手册在操作码表的描述列中特别提到了符号扩展。在这种情况下,它没有被提及,所以我想知道如果我碰巧使用负的 32 位立即数(换句话说,需要所有 32 位)会发生什么。
这是我测试过的汇编代码:
然后我从 C 中调用了imm_test函数:
如果要对 32 位立即数进行符号扩展,我假设必须打印的值为-2097153
,当使用 NASM 进行汇编和 GCC 编译和链接时,这正是打印的内容。
然而 NASM 给了我这个警告:
但是,再次查看反汇编代码,该指令的编码方式与我期望的完全一样:
它是一个 32 位立即符号扩展为 64 位。
当我将汇编代码的语法更改为 GAS 时.intel_syntax noprefix
,如下所示:
并尝试使用 GNU 汇编器来组装它,我不只是得到一个警告,我得到一个错误:
将说明更改imul
为正确记录的imul rax, rax, 0xFFDFFFFF
版本不会改变任何内容。
所以我想知道,为什么文档imul
如此不一致,为什么官方支持 32 位立即数(并且也可以正常工作),但它们却给出错误或警告?
assembly - ARM 程序集中的立即值编码
我现在正在学习汇编语言,我对立即值的编码方式有点困惑。有人可以解释为什么以下值有效:0xff00ff00、0xffffffff、0x007f8000?另外为什么值 0xff0000ff, 0x007f9000 无效?
据我了解,12 位立即数分为 4 个高位旋转和 8 个低位常量。所以我认为我上面列出的所有值都是无效的,因为它需要超过 12 位。
关于这个主题的一些澄清会很有帮助,谢谢!
assembly - 如何将 64 位二进制文字移动到 rax?错误 A2071:初始化程序幅度对于指定大小来说太大
这是我的代码。如果我将二进制值的大小减半为 32 位,它可以工作,但是一旦我尝试 33 位或更高位,我就会得到“错误 A2071:初始化程序幅度对于指定大小而言太大”
这是我的代码:
据我所知,rax 是一个 64 位寄存器,如果我使用这个二进制数的实际数字表示(即 18,446,744,073,709,551,615 = 2^64 - 1),那么它可以工作......但如果我尝试使用 33 或更多实际位值,程序不会汇编
有谁知道如何解决这一问题?
谢谢