- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我正在尝试将一个函数从 c 重写为汇编,这更像是一种用 C 编写汇编的练习,而不是提高它的效率。
我遇到的问题是我在三个 asm() block 中有工作代码,但我似乎无法将它们组合起来。我认为在组合它们时一定有一些我遗漏的东西。
这是目前有效的代码:
137 __asm__ __volatile__ (
138 "mov R0, #1\n\t"
139 "mov R1, %[bb]\n\t"
140 "and R0, R1\n\t"
141 "cmp R0, #1\n\t" // (b & 1) == 1
142 "bne aftereor\n\t"
143 "eor %[pp], %[pp], %[aa]\n\t"
144 "aftereor:\n\t"
145 "mov %[hbs], %[aa]\n\t"
146 "mov R0, #128 \n\t"
147 "and %[hbs], R0 \n\t"
148 "lsl %[aa], %[aa], #1\n\t"
149 : [pp]"+l" (p),[aa]"+l" (a),[hbs]"=l" (hi_bit_set)
150 : [bb]"l" (b)
151 :
152 );
153 __asm__ __volatile__ (
154 "cmp %[hbs], #128 \n\t"
155 "bne brancha \n\t"
156 "mov R2, #0x1b\n\t"
157 "eor %[aa], %[aa], R2\n\t"
158 "brancha:\n\t"
159 : [aa]"+l" (a)
160 : [hbs]"l" (hi_bit_set)
161 :
162 );
163 __asm__ __volatile__ (
164 "lsr %[bb], %[bb], #1"
165 : [bb]"+l" (b)
166 :
167 :
168 );
这是我试图用汇编重写的 C 代码:
if((b & 1) == 1) {
p ^= a;
}
hi_bit_set = (a & 0x80);
a <<= 1;
if(hi_bit_set == 0x80) {
a ^= 0x1b;
}
b >>= 1;
以上两段代码都按预期工作。但是,我的问题是将三个组装 block 合二为一。例如,由于某些原因,以下代码无法按预期工作。
137 __asm__ __volatile__ (
138 "mov R0, #1\n\t"
139 "mov R1, %[bb]\n\t"
140 "and R0, R1\n\t"
141 "cmp R0, #1\n\t" // (b & 1) == 1
142 "bne aftereor\n\t"
143 "eor %[pp], %[pp], %[aa]\n\t"
144 "aftereor:\n\t"
145 "mov %[hbs], %[aa]\n\t"
146 "mov R0, #128 \n\t"
147 "and %[hbs], R0 \n\t"
148 "lsl %[aa], %[aa], #1\n\t"
149 "cmp %[hbs], #128 \n\t"
150 "bne brancha \n\t"
151 "mov R2, #0x1b\n\t"
152 "eor %[aa], %[aa], R2\n\t"
153 "brancha:\n\t"
154 "lsr %[bb], %[bb], #1"
155 : [pp]"+l" (p),[aa]"+l" (a),[hbs]"+l" (hi_bit_set),[bb]"+l" (b)
156 :
157 :
158 );
我所做的唯一更改是将第二个和第三个 block 合并到第一个 block 中,将变量“hi_bit_set”和“b”更改为可读写。据我了解,这对我来说似乎很好。然而,这并没有产生正确的结果,所以我猜我错过了一些东西。
预先感谢您的帮助。
最佳答案
你看过'early clobber'了吗? ?编译器将为输入和输出分配相同的寄存器,您需要将一些寄存器保留更长时间并且需要将它们分开。
此外,您没有告诉编译器您使用“R0”、“R1”和“R2”作为显式寄存器。您应该创建一个“tmp1”变量并将其作为输入传递;称它为“R0”,您可以使用寄存器 asm
实际分配它(或将它们列为 clobbers)。
该代码充满了许多潜在的优化,可能只有 50% 的大小。但是,我会忠实于您的原件,但会指定寄存器以使其正常工作。
void foo(uint32_t a, uint32_t b, uint32_t p)
{
register uint32_t tmp1 asm ("r0");
register uint32_t tmp2 asm ("r1");
register uint32_t tmp3 asm ("r2");
uint32_t hi_bit_set;
__asm__ __volatile__ (
"mov R0, #1\n\t"
"mov R1, %[bb]\n\t"
"and R0, R1\n\t"
"cmp R0, #1\n\t" // (b & 1) == 1
"bne aftereor\n\t"
"eor %[pp], %[pp], %[aa]\n\t"
"aftereor:\n\t"
"mov %[hbs], %[aa]\n\t"
"mov R0, #128 \n\t"
"and %[hbs], R0 \n\t"
"lsl %[aa], %[aa], #1\n\t"
"cmp %[hbs], #128 \n\t"
"bne brancha \n\t"
"mov R2, #0x1b\n\t"
"eor %[aa], %[aa], R2\n\t"
"brancha:\n\t"
"lsr %[bb], %[bb], #1"
: [pp]"+l" (p),[aa]"+l" (a),[hbs]"+l" (hi_bit_set),[bb]"+l" (b)
:
: "r0", "r1", "r2" /* THIS IS IMPORTANT! */
);
}
这output appears good而如果我不包括 clobber 寄存器,编译器会使用“R0”等用于其他目的。编译器的主要工作是管理寄存器。在堆栈上压入/弹出是不好的(溢出),但不需要的 MOV
指令也是如此。
提出问题时,提供可编译的完整函数总是好的。我试着做了一个,你可以看到“GCC”是如何翻译你的功能的。您可以使用“进位标志”而不是常量来提取设置位信息。
#include <stdint.h>
uint32_t foo(uint32_t *A, uint32_t *B, uint32_t p)
{
uint32_t a = *A;
uint32_t b = *B;
/* codes starts here... */
if((b & 1) == 1) {
p ^= a;
}
a <<= 1;
if(a & 0x100) {
a ^= 0x1b;
}
b >>= 1;
/* codes is done. */
*A = a;
*B = b;
return p;
}
这是 gcc 的 16 位 thumb 输出,
foo(unsigned long*, unsigned long*, unsigned long):
push {r4, r5, lr} ; save callee reg
ldr r4, [r1] ; get 'B' pointer, your [bb] is r4.
ldr r3, [r0] ; get 'A' pointer, your [aa] is r3.
; codes starts here...
lsls r5, r4, #31
bpl .L2
eors r2, r3
.L2:
lsls r3, r3, #1
lsls r5, r3, #23
bpl .L3
movs r5, #27
eors r3, r5
.L3:
lsrs r4, r4, #1
; code is done
str r3, [r0] ; saving [aa]
movs r0, r2 ; r0 is 'pp'
str r4, [r1] ; save [bb] value.
pop {r4, r5, pc} ; restore to callers value.
汇编编码器可能更喜欢 local labels对于上面的“.L2”和“.L3”标签。
关于c - 在 C 中组合 ASM block 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41894703/
我需要处理来自旧 Mac 时代(旧摩托罗拉 CPU)的文件。字节是大端字节序,所以我有一个函数可以将 Int64 交换为英特尔小端字节序。该函数是 ASM,可在 32 位 CPU 上运行,但不能在 6
1.概述 转载:史上最通俗易懂的ASM教程 一勺思想 We are all in the gutter, but some of us are looking at the stars. (我们都生活
1.概述 转载:ASM 与 Presto 动态代码生成简介 代码生成是很多计算引擎中常用的执行优化技术,比如我们熟悉的 Apache Spark 和 Presto 在表达式等地方就使用到代码生成技术。
我想在 C++ 程序中使用 ASM 调用地址为 774a7fdch 的函数(kernel32.dll 函数) 我正在使用 Visual Studio 2010。 我该怎么做? call 774a7fd
我是否正确转换了它? 原始 VS C++ 版本: _TEB *pTeb = NULL; _asm { mov eax, fs:[0x18];
阅读自howto_add_systemcall "In general, header files for machine architecture independent system calls
在实现无锁数据结构和时序代码时,通常需要抑制编译器的优化。通常人们使用 asm volatile 和 clobber 列表中的 memory 来执行此操作,但有时您只会看到 asm volatile
这个“strcpy”函数的目的是将src的内容复制到dest,结果很好:显示两行“Hello_src”。 #include static inline char * strcpy(char * de
我正在尝试进行一些汇编编码,我从 C 语言调用函数。代码本身运行良好,但我有两个巨大的问题在很长一段时间内无法解决。第一个是语法高亮 - 我安装了两个不同的(当时一个)asm 高亮扩展到 Visual
我正在研究一些类文件分析,并且正在研究使用 ASM 来读取类。在 Javap 中,操作码以及 tagName 和 tagValue 是内联打印的,但在每个 AbstractInsnNode 中,我只看
我正在尝试弄清楚如何将 ASM 中的 DB 变量用于内联 ASM C++ 我有这个 ASM 代码: filename db "C:\imagen.bmp" eti0: mov ah,3dh mov a
这个“strcpy”函数的目的是将src的内容复制到dest,结果很好:显示两行“Hello_src”。 #include static inline char * strcpy(char * de
在 mm/memory.c 中,它包含一个文件: #include tlb.h 是 include/asm-generic/tlb.h或 arch/arm/include/asm/tlb.h ? 最
你好我找到了一个asm代码......它被集成到c++项目中 template T returned; BYTE *tem = buffer; __asm { mov eax, tem
问题:当我运行 @ 命令提示符 >tasm HelloWorld.asm 顺便说一句,我在输入文件名 HelloWorld.asm 时使用 TAB,所以没有错字.我收到这个致命的命令行错误: Turb
尝试通过 eax 从 asm proc 返回一个 long int,后来又尝试通过 dx:ax。两者都不适合我,因为 C printf 打印的数字与所需的 320L 不同。 x.asm: .model
这是 godbolt 生成的代码. 下面是 Visual Studio 在我的 main.asm 文件上生成的相同代码(通过 Project->C/C++->Output Files->Assembl
在构建具有依赖项的 giraph jar 时,我们收到以下警告.. 真的不知道如何解决这些.. 我们已经尝试过了 useProjectArtifact 为 false 和 解压为真 两者似乎都有效 任
我正在使用 gentoo 并尝试编译一个程序来控制并行端口上的位。它的顶部附近有这条线: #include 当我尝试在其上使用 gcc 时,它会产生以下输出: port.c:4:20: error:
(原帖)将 hibernate 依赖项添加到 pom.xml 时显示错误 2011-10-11 10:36:53.710::WARN: failed guiceFilter java.lang.No
我是一名优秀的程序员,十分优秀!