const data = [
{name: 'A', flag: 0},
{email: 'B', flag: 0},
{address: 'C', flag: 0},
{name: 'A1', flag: 1},
{email: 'B1', flag: 1},
{address: 'C1', flag: 1}
];
const res = data.reduce((a,{flag, ...rest})=>{
return a.set(flag, {...a.get(flag), ...rest});
}, new Map()).values();
console.log([...res]);
当我尝试汇编以下宏(在GNU / Linux Debian x86-64上使用GCC)时,汇编器会生成.macro alloc_linked_list_item_rdi_rax
movq $24, %rdi
call malloc@PLT
testq %rax, %rax
leaq 0x1a(%rip), %r10
jz *%r10 # <=
movq $0xA, 0x0(%rax) # void *data
movq $0x0, 0x8(%rax) # struct linked_list_item *prev
movq $0x0, 0x10(%rax) # struct linked_list_item *next
.endm
,其中ll.s:86: Error: operand type mismatch for 'jz'
指向此宏中的特定{{1} }。
对于这个宏,我尝试使用本地标签来管理控制流,但是它提出了一个错误,即我不能使用重复的标签名(因为我在程序中两次使用了宏),所以我转向带着倾向跳到RIP(通过使用ll.s:86
并随后计算指令的长度来计算)。
如果我将jz
替换为无条件的objdump
,那么给定的程序集就可以工作,因为对此,我对为什么我编写的代码不起作用感到困惑。
有人能阐明一些想法吗?
答案 0 :(得分:0)
x86指令集仅具有带有立即操作数的条件跳转(描述相对于程序计数器的偏移量)。其他操作数需要无条件跳转指令。解决此问题的一种简单方法是反转跳转的感觉,并跳过无条件的跳转指令,如下所示:
jnz .Lalloc_linked_list_item_rdi_rax.\@
jmp *%r10
.Lalloc_linked_list_item_rdi_rax.\@:
(有趣的标签名称旨在避免与其他标签冲突。)
如果我没记错的话,一些旧的汇编器会自动执行此操作,但是当静态分支预测到达CPU时,这变得不那么有用,并且实际上相当混乱,因为它掩盖了CPU如何预测分支。 (但是,当前大多数x86 CPU似乎不再非常依赖静态分支预测,因此我们回到了起点。)