如何仅使用 64 位寄存器在 64 位寄存器中存储 1 个字节值?
Posted
技术标签:
【中文标题】如何仅使用 64 位寄存器在 64 位寄存器中存储 1 个字节值?【英文标题】:How can I store 1byte value in 64bit register only using 64bit registers? 【发布时间】:2019-04-21 01:20:18 【问题描述】:我只需要使用 %rax、%rbx、%rcx、%rdx、%rsi 和 %rdi(还有 %rsp 和 %rbp)编写像素化汇编代码
所以我首先用 C 编写代码,并将任何其他寄存器更改为 64 位寄存器,但在下面我更改寄存器时,它提供了分段默认值
C 代码:
*temp = b;
*(temp + 1) = g;
*(temp + 2) = r;
gcc 的汇编代码:
movq -48(%rbp), %rax
movl %eax, %edx
movq -16(%rbp), %rax
movb %dl, (%rax)
movq -16(%rbp), %rax
addq $1, %rax
movq -56(%rbp), %rdx
movb %dl, (%rax)
movq -16(%rbp), %rax
addq $2, %rax
movq -64(%rbp), %rdx
movb %dl, (%rax)
将 %dl 更改为 %rdx:
movq -16(%rbp), %rax
movq -48(%rbp), %rdx
movzbq (%rdx), %rbx
movq %rbx, (%rax)
movq -16(%rbp), %rax
addq $1, %rax
movq -56(%rbp), %rdx
movzbq (%rdx), %rbx
movq %rbx, (%rax)
movq -16(%rbp), %rax
addq $2, %rax
movq -64(%rbp), %rdx
movzbq (%rdx), %rbx
movq %rbx, (%rax)
【问题讨论】:
你为什么要这样做? 鼓励打开编译器优化,顺便说一下,汇编输出会更短。 不清楚您要做什么以及为什么。无论如何,如果您只允许使用 64 位存储,如果您只想更新 3 个字节(然后您应该确保所有 8 个字节都可以访问),您将需要一个 read-modify-write。%dl
是%rdx
的低字节。您确定您的教授不只是告诉您避免使用 RBX(在 x86-64 System V 调用约定中保留调用)和 R8..R15?
好的,那么您所做的任何字节操作都必须使用 AND 掩码、移位和 OR。或者使用movzbq
从内存中加载。但是你不能做狭窄的商店。 (您可以读取/修改/写入一个 qword 并合并到一个新字节中,但这非常慢。如果您有多个相邻的字节存储要做,请先将它们合并到一个寄存器中并进行一个存储。)
【参考方案1】:
我认为你想做这样的事情:
t = r & 0xff;
u = *temp & ~ 0xfful;
*temp = u | t;
t = (g & 0xff) << 8;
u = *temp & ~ 0xff00ul;
*temp = u | t;
t = (b & 0xff) << 16;
u = *temp & ~0xff00000ull;
*temp = u | t;
您应该只能使用 64 位 reg 来编写它。您还应该能够找到一大堆方法来使这种方式比这更小。
【讨论】:
以上是关于如何仅使用 64 位寄存器在 64 位寄存器中存储 1 个字节值?的主要内容,如果未能解决你的问题,请参考以下文章
汇编 IA-32:如何将 64 位有符号数除以奇数(存储在 2 个寄存器中)
如何将两个打包的 64 位四字加载到 128 位 xmm 寄存器中